簡體   English   中英

C / C ++中的執行順序是否始終相同

[英]Is the order of execution always the same in C/C++

這段代碼總會產生相同的結果嗎?

return c * (t /= d) * t * t + b;

所以我期待:

return ((c * (t / d) ^ 3) + b);

但我不確定編譯器是否也可以將其解釋為:

return ((c * t * t * (t / d)) + b)

我已經在C標准中搜索但找不到答案,我知道x = x++是未定義的但是在這里我不確定因為t /= d周圍的()我認為迫使編譯器首先計算該語句。

我在C標准中搜索過但找不到答案

你要搜索的是序列點

你的表達

c * (t /= d) * t * t + b

不包含任何序列點,因此可以以任何相對順序評估子表達式。


請注意 ,這適用於C,因為您在問題中提到過。 您還標記了相關但非常不同的語言C ++,它具有不同的規則。 幸運的是,在這種情況下,他們給出了完全相同的結果。

2014-11-19工作草案PDF:N4296的相關文字是

1.9程序執行[intro.execution]

...

14在與要評估的下一個完整表達式相關聯的每個值計算和副作用之前,對與完整表達式相關聯的每個值計算和副作用進行排序。

15 除非另有說明,否則對單個算子的操作數和個別表達式的子表達式的評估是不確定的 [注意:在程序執行期間不止一次評估的表達式中,不需要在不同的評估中一致地執行對其子表達式的未序列和不確定順序的評估。 - 結束注釋]在運算符的結果的值計算之前,對運算符的操作數的值計算進行排序。 如果對標量對象的副作用相對於同一標量對象的另一個副作用或使用相同標量對象的值進行的值計算未被排序,並且它們不可能並發(1.10), 則行為未定義 [注意:下一節對潛在的並發計算施加了類似但更復雜的限制。 - 結束說明]

因此,C ++中的邏輯是,除非對事物進行明確排序(例如,通過a ;分離兩個完整表達式),否則它們可以按任何順序發生。

正如(第二個)突出顯示的部分所提到的,當兩個未按順序的子表達式修改同一個對象(或者一個修改並且一個讀取)時,行為是未定義的。

以下聲明:

return c * (t /= d) * t * t + b;

在C中調用未定義的行為 (我也相信C ++)。 這是因為t被評估兩次(計算(t /= d)子表達式),盡管有副序列的副作用(由復合賦值算子產生),這影響了由t變量表示的對象。

遇到UB的那一刻是你應該停止思考表達的“正確”價值的那一刻。 沒有,因為一切皆有可能,包括關閉你的電腦。

最近版本的gccclang-Wall可能會告訴你表達式被懷疑是在調用UB。 這里的警告是:

警告:'t'上的操作可能未定義[-Wsequence-point]

警告:無序修改並訪問't'[-Wunsequenced]

上面的表達式,括號使操作順序顯式,如下所示:

return ((((c * (t /= d)) * t) * t) + b);

然而,這里的問題是該表達式中沒有序列點 因此,可以按任何順序評估任何子表達式。

例如,編譯器可以選擇評估t的值一次,然后使用它出現的每個位置的原始值。 相反,它可能首先評估修改t t /= d ,然后在其出現的任何其他位置使用此修改值。

簡而言之,因為您在沒有序列點的單個表達式中讀取和寫入變量,所以您調用未定義的行為

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM