2010-11-08 66 views
3

我(基本上)遇到下列野生未定義行爲或假陽性

x = x = 5; 

這顯然編譯乾淨的gcc下的早期版本(生成下GCC 4.5.1警告)來了。據我所知,警告是由-W序列點產生的。所以我的問題是這是否違反了標準中關於在序列點之間操縱變量的標準(即,它是每個規範未定義的行爲)還是這是gcc誤報(即,它是按照規範定義的行爲)?順序點的措辭有點難以遵循。

我基本上是說,因爲我居然遇到了(在一個更大的表達式)是

x[0][0] = x[0][0] = 5; 

,但我不認爲這是材料的警告(請糾正我,如果這是在點不是我所認爲的是問題的關鍵)。

+3

無論是否違反標準中的措辭,都是代碼糟糕。用火殺死它!讓這樣一個表達式再也不會讓你的代碼變暗。 – abelenky 2010-11-09 00:17:57

+0

@abelenk同意。這不是我的代碼,我想確保在將它提交給CCB之前是UB。 – bpw1621 2010-11-09 00:31:53

回答

5

假設x是內置類型,它分配給x兩次沒有干預序列點,這是你所需要知道的。這兩個任務具有相同的值(5),並且理論上可以優化爲單個任務(如果x不是不穩定的),這個事實既不在這裏也不在那裏。

至少,這就是我解釋標準中「修改」的方式 - 分配了一個值,而不管它是否與舊值相同。同樣,拋出const並分配給一個const對象,我認爲是UB,不管你分配的值是否等於先前的值。否則,如果實現需要將字符串文字放入ROM中,以防止出現頁面錯誤,並且我們通過檢查編譯器不會發出該代碼,則所有內存寫入都會有巨大開銷。

甲更令人興奮的例子是x[0][0] = x[0][i] = 5;,如果(且僅當)i == 0,所以被定義行爲上的i值條件,其分配給同一對象而沒有介入的序列點。

我不明白爲什麼很編譯器可能會做任何事情,意外在任何情況下,但我又缺乏想像力是無關緊要的:-)

說什麼ablenky是正確的。如果您在某些情況下無法使用兩條語句,則可以改爲寫x[0][0] = 5, x[0][i] = 5。在你給定的情況下,只是拋棄冗餘分配。

+0

不嚴格正確:如果x碰巧是一個帶有operator =的用戶定義類型,則x = x = 5具有與每個成員函數調用關聯的序列點,因此會生成定義的行爲。 – 2010-11-09 01:33:29

+0

@Tony:夠公平的。這正是我爲什麼說「假設x不是類類型」的原因,但我忘記了它有聯合類型的可能性。 – 2010-11-09 01:41:41

+0

對於內置類型是一個很好的答案,只是想要討論類,因爲這可能與海報是否可以將其標記爲他的「CCB」相關。 – 2010-11-09 01:49:00