2011-11-24 77 views
5

最近我迷茫了下面的C++代碼片段:表達式求值順序

#include <cstdio> 

int lol(int *k){ 
    *k +=5; 
    return *k; 
} 

int main(int argc, const char *argv[]){ 
    int k = 0; 
    int w = k + lol(&k); 
    printf("%d\n", w); 
    return 0; 
} 

看看行:

int w = k + lol(&k); 

到現在爲止我認爲這表達式將被評估,從左至右:取k的當前值(calall函數爲0之前),然後將其加到lol函數的結果中。但是編譯器證明了我,我錯了,W的值是10,即使我交換位置,使其

int w = lol(&k) + k; 

結果將是仍然10.我在做什麼錯?

託梅克

+0

沒有,'+'是最後一個操作 – volody

回答

3

這是因爲在表達式中的參數是指定在任何特定的順序進行評價。

編譯器首先可以自由執行參數klol(&k)。該表達式中沒有順序點。 這意味着參數的副作用可以以任何順序執行。

所以簡而言之,它沒有指定代碼是否打印510。兩者都是有效的輸出。

此例外是布爾表達式中的短路,因爲&&||是序列點。 (請參閱註釋)

+0

'&&','||'和'?:'出現在表達式中,是序列點。 –

+0

@MarceloCantos:感謝那些信息。我不確定使布爾表達式不同的確切語言語義。我澄清了我的答案。 – Mysticial

+0

請注意,只有內置的'&&'和'||'(以及',')是序列點。如果它們被重載,則它們變成兩個參數的函數,並且函數參數的評估順序是未指定的。 –

2

Plus按定義交換,所以示例中的順序完全由實現定義。

Mysticial是正確的時候提到順序點。援引Wikipedia article(不具有C++手邊標):

在命令性編程的序列點限定在它被保證先前評價的所有側 效果將一直處於 計算機程序的執行的任何點執行,並且沒有任何一方從後續評估中產生的影響尚未執行。它們是 經常在參考C和C++時提到,因爲某些 表達式的結果可能取決於其子表達式的評估順序。添加一個或多個序列點是 確保一致結果的一種方法,因爲這限制了可能的 評估順序。

該文章還列出了C++中的順序點。

+0

「_你的例子完全是實現定義的。」「不,它不是。沒有我知道的實現來定義會發生什麼。 – curiousguy

+0

@curiousguy:也許,我沒有說清楚。我應該說「特定實現」還是「特定於編譯器」? –

+0

或「依賴於實現」,或者只是「未指定」。 – curiousguy

3

根據函數調用相對於+左邊的評估或選擇的選擇,此代碼可以產生5或10。

它的行爲是而不是未定義,因爲函數調用被兩個序列點包圍。