2017-05-14 190 views
5

如果啓用了-Wsequence-point,當未定義的行爲代碼被發現時,GCC應該警告用戶。例如爲什麼在這個例子中GCC不會發出警告

b = a + ++a; 

應該由海灣合作委員會注意到,應報告爲「未定義行爲」的代碼(因爲ISO C沒有指定除了評估操作數的順序)。

不過,我打了語法,我想這一個:

int *a = malloc(sizeof(int) * 2); 
a[0] = 1; 
printf("%d\n", *(a + (*a)++ - *a)); 

當然,我得到了警告

警告:「*」可以未定義[操作 - Wsequence點]

這是我預期的,因爲*a的值(這是a[0])可以遞增或可以不同時處理第三個操作數。但是,我嘗試了以下一種:

int *a = malloc(sizeof(int) * 2); 
a[0] = 1; 
printf("%d\n", *(a + (*a)++ - 1)); 

我很驚訝,因爲我沒有收到警告。這不應該是UB嗎?我的意思是,根據ISO C99,可以在表達評估(除了逗號運算符和三元運算符除外)的任何點評估後增量操作。在我後面的例子中,我不是遞增指針,而是指向它的整數。因此,根據標準,它可以隨時增加(這意味着它可以在整個表達式評估後遞增),因此程序可能同時打印12,對不對?

爲什麼GCC不會發出任何警告?或者我錯過了什麼?我錯誤地理解了規格嗎?

回答

6

gcc的靜態分析工具不能處理這種情況。

表達*(a + (*a)++ - x)太難了,GCC的靜態分析,因爲這會導致不確定的行爲,由於在某些非常特殊的情況下,缺乏序列點 - 即,當*a包含x。這是當(*a)++ - x彼此「撤消」,所以整體表達等於*a加上一些副作用。

爲了讓海灣合作委員會代碼分析發現此錯誤,編譯器必須在其整個生命週期中跟蹤*a的內容。雖然在你的例子中它看起來很簡單,但是一個更復雜的程序,比如說,從用戶輸入中將數據讀入a,使得這種分析變得不可能。

相關問題