[英]Why does the following code give different results when compiling with gcc and g++?
#include<stdio.h>
int main()
{
const int a=1;
int *p=(int *)&a;
(*p)++;
printf("%d %d\n",*p,a);
if(a==1)
printf("No\n");//"No" in g++.
else
printf("Yes\n");//"Yes" in gcc.
return 0;
}
上面的代碼在g++
編譯中給出No
作為輸出,在gcc
編譯中給出Yes
。 任何人都能解釋一下這背后的原因嗎?
您的代碼會觸發未定義的行為,因為您正在修改const
對象( a
)。 它不必產生任何特定的結果,即使在相同的平台上,也不必使用相同的編譯器。
雖然沒有指定此行為的確切機制,但您可以通過檢查代碼生成的程序集來弄清楚您的特定情況下發生了什么(您可以通過使用-S
標志來查看。)請注意編譯器允許通過假定具有明確定義的行為的代碼來進行積極的優化。 舉例來說, a
可以簡單地通過更換1
無論在何處使用。
來自C ++標准(1.9程序執行)
4本國際標准中將某些其他操作描述為未定義( 例如,嘗試修改const對象的效果 )。 [注意:本國際標准對包含未定義行為的程序的行為沒有要求。 - 尾注]
因此,您的程序具有未定義的行為。
在您的代碼中,請注意以下兩行
const int a=1; // a is of type constant int
int *p=(int *)&a; // p is of type int *
您將const int
變量的地址放入int *
,然后嘗試修改該值,該值應該被視為const
。 這是不允許的,並調用未定義的行為 。
供參考,如第6.7.3章, C11
標准第6段所述
如果嘗試通過使用具有非
const
-qualified類型的左值來修改使用const
-qualified類型定義的對象,則行為是未定義的。 如果嘗試通過使用具有非volatile限定類型的左值來引用使用volatile限定類型定義的對象,則行為未定義
因此,長話短說,你不能依靠comaprison的輸出。 它們是未定義行為的結果。
好的,我們這里的“相同”代碼傳遞給“相同”的編譯器,但一次帶有C標志,另一次帶有C ++標志。 就任何合理的用戶而言,沒有任何改變。 代碼應該由編譯器完全相同地解釋,因為沒有發生任何重大事件。
實際上,那不是真的。 雖然我很難在標准中指出它,但對'const'的精確解釋在C和C ++之間略有不同。 在C中它是一個附加組件,'const'標志表示這個常規變量'a'不應該由這里的代碼寫入。 但它有可能被寫入其他地方。 對於C ++,重點更多地放在不可變常量概念上,編譯器知道這個常量更類似於普通變量的“枚舉”。
所以我希望這種微小的差異意味着生成稍微不同的解析樹,最終導致不同的匯編程序。
這種事情實際上是相當常見的,即使使用“相同的”編譯器,C / C ++子集中的代碼也不總是編譯為完全相同的匯編程序。 它往往是由其他語言特性引起的,這意味着有些東西你現在無法在其中一種語言中證明代碼,但在另一種語言中它是可以的。
通常C是性能優勝者(由Linux內核開發人員重新發現),因為它是一種更簡單的語言,但在這個例子中,C ++可能會變得更快(除非C dev切換到宏或枚舉並捕獲不合理的行為)獲取不可變常量的地址)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.