2010-10-09 41 views
-1
const int z = 420; 

printf("\n%d | %d",z ,*(&(*(&z+1))-1)); 
// O/P:420 | 420 

printf("\n%u | %u",&z,(&(*(&z+1))-1));    //address 
// O/P:1310548 | 1310548 

*((char *)&z+1) = 21;  //I change value for the 1st-Bit 
            //corrupting constant 

printf("\n%d | %d",z ,*(&(*(&z+1))-1)); 
//the complex(not really) expression evaluates to z 
// O/P:420| 5540 

printf("\n%u | %u",&z ,(&(*(&z+1))-1));     
//the complex(not really) expression evaluates to &z 
// O/P:1310548 | 1310548 

爲什麼會發生這種情況?在c中修改了一個常數

似乎我已經成功地使用C

修飾的恆定

通過修改我的意思是我在常數發生變化的位地址範圍

爲「複合物(不是真的)統一/標識表達」 腐敗後更改值。

但是z保持不變。爲什麼?

當解除引用時,同一個地址有多少個不同的值。 ?

PS:u可以使用任何身份表達

eg.printf("%d",*(int*)((char*)&(*((char*)&z+1))-1)); 

[編輯]

OK讓我重新措辭:有

z = 420 

&z = 1310548 

*(&(*(&z+1))-1) = 420 

(&(*(&z+1))-1) = 1310548 

我現在做的腐敗常數

*((char *)&z+1) = 21; 

現在經過腐蝕:

z = 420  // NO CHANGE EVEN THOUGH I have corrupted 

&z = 1310548 

*(&(*(&z+1))-1) = z = 5540 // THE CHANGE 

(&(*(&z+1))-1) = &z = 1310548 

爲什麼?

+0

也許編譯器通過將'z'放入寄存器來優化。然後你做了一些瘋狂的事情來訪問'z'的內存並改變它,所以編譯器實際上讀取內存。沒有任何優化就嘗試它會很有趣。 – Starkey 2010-10-09 15:25:57

+7

我不認爲C中的「const」意味着你認爲它的作用。 – 2010-10-09 15:27:00

+0

這是一些真正混淆的代碼。 – 2010-10-09 15:29:37

回答

5

這裏沒有很多神祕的東西。通過使用強制轉換告訴編譯器什麼你改變不const合格的,你造成未定義行爲:

6.7.3/5「類型的限定」(C99):

如果試圖通過使用帶有非const限定類型的左值的使用 來修改用const限定類型定義的對象,則行爲是未定義的。

某些實現可能已將變量z放在只讀內存中,並且您不會得到明顯的更改或某種訪問衝突。

在任何情況下,未定義的行爲意味着所有投注都關閉 - 在您的情況下,您可以看到const值的明顯修改。

6

恭喜你,你對編譯器撒謊了,它咬住了你。

投訴告訴編譯器您有意違反規則並暗示您知道自己在做什麼。當你這樣做的時候,C很高興能夠讓你在諺語的腳上自我射擊。

+0

hmm?仍然相同的地址取消引用給出了不同的答案.. – bakra 2010-10-09 15:30:32

+0

,因爲它沒有存儲在只讀存儲器中。'const'僅告訴編譯器它不應該被改變 – fazo 2010-10-09 15:36:59

6

你有什麼int const實際上不是一個常數,而是一個const限定對象。所以如果你玩通過指針操作來改變這個對象的遊戲,這可能是可能的,但是會傳遞未定義的行爲。

C中唯一的整數常量是數字標記,整數字符常量,如'a'enum常量。