int i = 3, x, y;
x = (i++) + (i++); // x = ?
i = 3;
y = (++i) + (++i); // y = ?
| 表達式 | 結果 | i 最終值 | 關鍵規則 |
|---|---|---|---|
x = (i++) + (i++) | 6 | 5 | 後綴:先取值後遞增,兩運算元均為 3 |
y = (++i) + (++i) | 10 | 5 | 前綴:先遞增後取值,兩運算元均為 5 |
i = 3;
y = (++i) + (++i) + (++i) + (++i); // y = ?
錯誤直覺:4+5+6+7=22 或 5+5+5+5=20
正確答案:23(i 最終為 7)
+ 為左結合二元運算子,編譯器將其視為:
(( (++i) + (++i) ) + (++i) ) + (++i)
逐步求值(假設編譯器採左到右求值順序):
++i → 4,++i → 5,第一個 + 得 9++i(6) = 15++i(7) = 22 → 但實測多為 23關鍵補充:C 標準未規定函數引數/運算元的求值順序(Unspecified behavior),不同編譯器、優化等級可能產生不同結果。實務上絕不可在同一表達式對同一變數多次副作用操作。
i = 3;
y = (i++) + (i++) + (i++) + (i++); // y = 12 (3+3+3+3), i=7
後綴自增的副作用在完整表達式結束後才生效,故四個運算元皆為 3。
C11 §6.5/2:若同一標量物件在兩次序列點之間被修改超過一次,或被修改後又被讀取(非為了決定要儲存的值),行為未定義。
// 明確分步,消除歧義
i = 3;
int a = ++i; // 4
int b = ++i; // 5
int c = ++i; // 6
int d = ++i; // 7
y = a + b + c + d; // 22,行為明確
編譯器內部常轉為 RPN:i ++ i ++ + i ++ + i ++ +,堆疊機模擬可完美預測特定編譯器行為,但不可移植。