int a = 1, b = 3, c = 0;
a = (++b) + (++b) + (++b);
printf("a=%d\nb=%d\n", a, b);
| 編譯器 | a 的值 | b 的最終值 |
|---|---|---|
| GCC (Linux) | 16 | 6 |
| MSVC (Windows) | 16 | 6 |
| Turbo C (DOS) | 18 | 6 |
| C# / Python (無 ++) | 15 (人工預期) | - |
C 標準規定:同一序列點內對同一標量對象多次修改,或修改後又讀取其值以確定新值,行為未定義。
表達式 (++b) + (++b) + (++b) 在單一語句中三次修改 b,且參與加法運算,完全屬於 UB 範疇。編譯器可隨意處理,結果不可移植。
// 關鍵片段簡化
addl $0x1, 0x1c(%esp) // b++ 第一次
addl $0x1, 0x1c(%esp) // b++ 第二次
movl 0x1c(%esp), %eax // 讀取 b(現為5)
addl %eax, %eax // eax = 5+5 = 10
addl $0x1, 0x1c(%esp) // b++ 第三次 (b=6)
addl 0x1c(%esp), %eax // eax = 10+6 = 16
movl %eax, 0x18(%esp) // 存入 a
執行順序:前兩次 ++b 先執行並累加,第三次 ++b 最後執行並加到和中。即 5 + 5 + 6 = 16。
反匯編顯示:三次 inc 連續執行(b 變 6),然後 add di, si 執行兩次(6+6+6=18)。屬於另一種 UB 實現。
a = (++b) + (b++) + (b++) → GCC: 12 (b=6)a = (b++) + (b++) + (b++) → GCC: 3 (b=6),三次後置遞增均在加法後執行a = (++b) + (++b) + (++b) + (b++) + (++b) + (++b) → GCC: 37 (b=9)int b = 3;
int t1 = ++b; // 4
int t2 = ++b; // 5
int t3 = ++b; // 6
a = t1 + t2 + t3; // 15,行為明確定義
這類代碼屬於「面試陷阱」或「惡作劇」,絕不可用於生產環境。C 語言的靈活性要求開發者自律:清晰表達意圖,拒絕依賴 UB 的巧技。