深入探討常量、指向常量的指標,常量與變數的區別

來源:互聯網
上載者:User

今天在csdn c區看到飛翔網友一個提問帖,雖然很簡單但感覺挺有意義的:

-------------------------------------------------------------------------------------------------------------------------

我在VC中編程時,寫了這樣兩句代碼。
    char * q = "Hello";
    *q = 'W';
編譯沒有錯誤。當運行到第二句時,總會提示這樣的錯誤:
Unhandled exception in GeneralTest.ext: 0xC0000005: Access Violation.
請問這是為何?
按理講,我只是通過指標更改其所指記憶體中的指而以,怎麼會出錯呢?怎麼又總是在0xC0000005處出錯呢?

--------------------------------------------------------------------------------------------

我在此將各位前輩對此問題的解答進行系統的整理。

此問題代碼中,"Hello"是一個常量,由於c/c++定義中常量是不能被修改的。所以儘管飛翔將儲存常量的地址賦給了一個指標,指標可以獲得這個常量的值,但是對它進行修改卻是非法的。

根據c/c++文法,當你聲明該量為常量,即告訴程式和編譯器,你不希望此量被修改。

程式的實現,為了保護常量,特將常量都放在受保護的靜態儲存區內。凡是試圖修改這個地區內的值,都將被視為非法,並報錯。

這不能理解為凡是字串都是放在靜態儲存地區的。這個跟資料類型沒有關係,而是這個量是變數還是常量的問題。例如,一個字串變數就是可以被修改的。

這種靜態儲存地區的保護機制是由編譯器實現的,而非儲存該值的記憶體的電器屬性。換言之,實質上記憶體永遠都可以被使用者隨意修改,只是編譯器給使用者的代碼注入了一些自己的保護代碼,通過軟體手段將這段記憶體軟保護起來。這種保護在彙編層級可以輕鬆突破,其保護也就無效了。

vc6的debug模式編譯結果給程式添加了這樣的保護,協助使用者儘早發現程式錯誤,而非此保護不可或缺。而release模式下對程式針對運行效率進行了最佳化,這樣的保護顯然是要消耗系統資源的,不利於提高效率。而且編譯器假定,一個要發布的想要在release模式下編譯的程式必然經過了debug模式的調試,已經處理了這樣的錯誤。所以此時在審查就是冗餘的了,vc6的release模式下放棄了對常量的保護。因此如果你的代碼沒有經過debug模式的編譯而直接release,就沒有人去檢查你是否修改了常量,也沒有人去禁止這個操作。

這並非說release模式下承認對常量修改的合法性,僅僅是不去管理罷了。vc6的release模式下放棄了對常量的保護,但是其他的實現未必這樣做,這要具體看你的實現環境了。

從本質上說,對於機器,對於硬體是不存在常量與變數的區別的。它們都是記憶體中被分配了的一段記憶體空間罷了。甚至不存在資料類型上的區別。對所有的資料來說,記憶體都是一樣的。資料之間的相互區別也是通過存在記憶體中的資料實現的。

對於這方面,學習過彙編的朋友會比較清楚。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.