2014-12-02 37 views
2

我想了解const在C++中。 我寫這下面的代碼片段:我通過訪問內存位置來更改const變量的值。爲什麼它不起作用?

const int x=5; 
int *ptr; 
ptr=(int*)&x; 
cout<<"address of x="<<&x<<endl; 
cout<<"value of ptr="<<ptr<<endl; 
*ptr=11; 
cout<<"*ptr="<<*ptr<<endl; 
cout<<"x="<<x; 

輸出是

address of x=0x28fef8 
address of ptr=0x28fef8 
*ptr=11 
x=5 

由於PTR指向X,我相信在* PTR的價值和X都將是相同。 爲什麼數值不同? 我明白x是常量,但是,我做* PTR改變在內存地址的值。 請告訴我我錯過了什麼。

+2

修改'const'變量的值會導致未定義的行爲。 – CoryKramer 2014-12-02 20:14:11

+0

@Cyber​​即使我們修改其地址的值?爲什麼這樣? – SeasonalShot 2014-12-02 20:16:11

+2

因爲你騙了編譯器。你告訴它'x'永遠不會改變,所以它可能會根據這個假設做出假設。 – 2014-12-02 20:17:29

回答

3

官方答案(如C++語言標):

未定義的行爲。

實用的答案(取決於編譯器實現):

隨着全球const int x=5,該變量在可執行映像的RO-數據部分分配。

執行*ptr=11因此將運行時的非法存儲器存取的異常的結果。

使用本地const int x=5,該變量分配在可執行映像的(RW)堆棧部分。

但由於x是恆定的,編譯器代替這個變量與5.

6

您的C風格的類型轉換是消除常量性,使得分配成爲可能。之後,你寫入一個值爲const的值。這會調用未定義的行爲,然後事情就會發生。這也意味着沒有辦法解釋你所看到的輸出。最有可能的是,編譯器假定這個值永遠不會改變,只是使用常量摺疊,因此你得到了x=5,但我們永遠不會知道。

外賣:C風格的轉換都是邪惡的,幾乎不再需要。

+1

我同意C風格的演員是邪惡的。但是你可以使用'const_cast'獲得相同的未定義行爲。至少它突出了更多。 – 2014-12-02 20:21:54

+0

好吧,我現在看到。所以頁表只是「假設」x的值將是5「永遠」。在任何情況下,我永遠不會再嘗試這個我雖然這是一種黑客。但我想我的懷疑已經清除了。謝謝! – SeasonalShot 2014-12-02 20:24:34

+0

@FredLarson「伸出更多」,如「巨大的紅色警告標誌與字母SOMETHING愚蠢即將發生」?是的,它確實。 – pmr 2014-12-02 20:39:40

1

「常量」告訴編譯器,如果任何人寫道,嘗試修改該對象的代碼/變量的值,每一個r值參考然後拋出一個編譯錯誤來阻止他們這樣做,並且順便說一下,如果在這種情況下值沒有改變,你可以自由地進行任何優化。一個C風格的cast/const_cast說,我知道我在做什麼,不要打擾我拋出錯誤,因爲無論如何我都會這樣做。所以通過這兩個你是危險的生活。有時候你會放棄它,有時候系統會得到你。當您嘗試寫入時,放入.rodata中的變量是否導致異常取決於平臺。如果您沒有硬件內存保護,並且所有代碼都是從RAM運行的,那麼您可以在需要的地方寫入很多內容,包括覆蓋代碼(.text)。對我來說,常量的美妙之處在於它具有傳染性(正因爲如此,其他人稱它爲邪惡或混亂)。

+0

'const'是上帝tbh – 2014-12-02 22:49:21

相關問題