爲什麼下面的代碼產生這樣的輸出:行爲遞增運算符作爲參數傳遞給函數
代碼段:
int a=10;
printf("%d%d%d",++a,a++,++a);
輸出:
131113
如何爲參數進行評估?這是否依賴於編譯器?我使用gcc編譯器。任何人都可以告訴我編譯器如何評估它嗎?如果編譯器從右到左評估函數的參數,則該代碼的輸出如下:
121111
爲什麼下面的代碼產生這樣的輸出:行爲遞增運算符作爲參數傳遞給函數
代碼段:
int a=10;
printf("%d%d%d",++a,a++,++a);
輸出:
131113
如何爲參數進行評估?這是否依賴於編譯器?我使用gcc編譯器。任何人都可以告訴我編譯器如何評估它嗎?如果編譯器從右到左評估函數的參數,則該代碼的輸出如下:
121111
這是未定義的行爲。在sequence point中多次修改變量是未定義的行爲。
來自維基:從後續
的序列點限定在它被保證以前 評價所有的副作用將已被執行在計算機程序的執行 任何點,且無副作用評估尚未完成。
請閱讀:Operator Precedence vs Order of Evaluation
進行徹底的瞭解,請閱讀:Undefined Behavior and Sequence Points
你雖然可以做到這一點:
int a=10;
int b = (++a,a++,++a);
因爲逗號(,)是運營商在這裏和不是僅僅是參數之間的分隔符,如printf
的情況。
這實際上是unspecified behavior和undefined behavior的組合。
這是不確定因爲沒有指定的函數參數計算順序是這樣在這條線:
printf("%d%d%d",++a,a++,++a);
^ ^^^
1 2 3 4
我們不知道函數的參數1
到4
將評估其順序做,它甚至可能的是,如果這是在後續執行的循環中,順序可能不同。這是包括在C99標準草案部分6.5.2.2
函數調用款它說(重點煤礦):
的秩序評價功能標誌,實際的參數,並 實際參數內的子表達式未指定,但在實際調用之前有一個序列點 。
就其本身而言,這意味着該程序的輸出是不可靠的,但我們也有未定義行爲由於上面的代碼修改一個sequence point內a
多次。
之前和下一序列點的對象應具有至多一次改性其存儲的值 之間:這是通過部分
6.5
表達式段落它說(重點礦山)覆蓋表達的評估。 72)此外,先驗值只能讀取以確定要存儲的值。 73)
未定義行爲意味着什麼事情都可能運行此程序包括它似乎正常工作造成的,該術語部分3.4.3
限定,幷包括以下注這也解釋了可能的結果的未定義行爲:
可能的不確定的行爲從不可預知的結果完全無視形勢的範圍,以translat期間表現離子或程序以環境特徵(有或者沒有發佈診斷消息)的文件化方式執行,終止翻譯或執行(通過發佈診斷消息)。
除此之外,即使你能獲得可靠的結果,這樣的代碼是難以閱讀,將是一個複雜的項目,以保持一個噩夢。如果有其他更簡單的方法來編寫符合其他要求的代碼(如性能等),那麼這就是您應該採取的方法。
未定義的行爲。在計算表達式之前,你可以指望'++ a'遞增,或者後面的是'a ++',但是你不能指望在同一個順序點內進行動作的順序。 – DavidO
它取決於編譯器。不能保證任何兩個編輯會有相同的順序,甚至。 – Gabe
正確:它是依賴於實現的,但行爲沒有在標準中定義,也不能依賴於在同一個編譯器的未來版本中,甚至在不同的大氣壓力下更改。 ;) – DavidO