2011-05-16 115 views
10

閱讀this這個話題後,我還是有點困惑。以下C++表達式*d++ = ~(*d);是否定義良好?是的,我知道這樣的複合表達是醜陋的..我沒有寫它。這是明確的代碼?

我看到生成的程序略有不同,當我把它比作:

*d = ~(*d); 
d++; 

大會:

*d++ = ~(*d); 
0x83384 LDR   R3,[R0 <d>,4]  <<diff 
0x83388 ADD   R1 <c>, R1 <c>, 1 
0x8338c MVN   R3, R3 
0x83390 STR   R3,[R0 <d>],4 

VS

*d = ~(*d); 
d++; 
0x83384 LDR   R3,[R0 <d>] 
0x83388 ADD   R1 <c>, R1 <c>, 1 
0x8338c MVN   R3, R3 
0x83390 STR   R3,[R0 <d>],4 

謝謝!

+0

所有彙編是要告訴你的是什麼這個特殊的編譯器的這個特定版本與您使用這個特定時刻的設置一樣。它沒有說什麼是標準保證或不保證的。 – 2011-05-16 22:25:09

+0

謝謝。我最初認爲在這個問題的背景下看看編譯器產生了什麼可能會有所幫助。我現在看到任何東西(在未定義的情況下)都可能產生。 – Mav3rick 2011-05-16 22:42:09

回答

9
*d++ = ~(*d); 

在這個表達式中,沒有任何對象多次存儲新的值。 d + 1的值作爲增量運算符(d++)的副作用和d指向的對象的值存儲到d,然後該賦值運算符將寫入該增量。

問題是d被讀取時,不只是確定該值被寫回它(即d + 1),但也被讀取以確定從在右側子表達式~(*d)讀出地址。

這違反了ISO/IEC 14882的第三個句子:2003 5 [EXPR]/4(爲簡潔起見省略第一句):

[...]的前一個和下一個序列點之間的標量對象應通過評估表達式將其存儲值最多修改一次。 此外,只有在確定要存儲的值時才能訪問先前值。對於完整表達式的子表達式的每個允許排序,應滿足本段的要求;否則行爲是不確定的。

+0

這是一個非常有用的解釋。謝謝。 – Mav3rick 2011-05-16 22:19:15

11

你的表達具有未定義(相對於未指定)行爲。彙編代碼也可以播放貝多芬9號,並且仍然符合標準。

從神聖的標準,第5章,第4節:

之前和下一序列點之間的標量對象應具有其存儲的值由表達式的評估修飾的至多一次。

因此,代碼格式不正確。我不知道是否符合標準的編譯器需要需要才能發佈診斷,但我已經被足夠多的時間通過這個,我準備好打賭它不是。

有關更多詳細信息,請參閱@Prasoon Saurav的優秀博覽會there

+0

我希望它能做到。 – Femaref 2011-05-16 21:12:52

+0

* *會是非常可怕的! :) – FrustratedWithFormsDesigner 2011-05-16 21:13:00

+0

@coward downvoter:請澄清你的意圖。我很確定這是每個OP指向的鏈接都是UB,但我可能是錯的。 – 2011-05-16 21:15:38

1

你只是不知道++何時被評估。我想你的編譯器,導致

*d = ~(*(d+1)); 

因此您dicrepancy的~(*d)之前對其進行評估。

+0

不要假設任何東西。沒有什麼可設想的,代碼是根據C++ ISO標準生成的。 – 2011-05-16 21:23:29

+0

我覺得你的意思* d =〜(*(d + 1)),如果你指的是RHS查找前++生效。 – 2011-05-16 21:58:32

+0

@Alexander C.,我認爲基督教是說,拆卸例子表明,一些特定的編譯器第一次做的增量,這將是比對排序的組件(或預期)不同。 – 2011-05-16 22:02:19