| 運算符 | 名稱 | 值 | 副作用完成時機 |
|---|---|---|---|
k++ | 後置遞增 | **遞增前**的值 | 序列點 (語句結尾、,、?:、||、&&) |
++k | 前置遞增 | **遞增後**的值 | 序列點 (同上) |
int k = 5;
printf("%d %d %d\n", k++, ++k, k); // 未定義行為 (UB)!同一序列點多次修改 k
// 輸出可能是 5 7 7 / 6 6 7 / 崩潰 / 任意值 — 編譯器隨意
**鐵律**:同一表達式/語句中,**不要對同一變量進行多次修改或修改後再讀取** (除非用序列點分隔)。
k++; // 效果等同 ++k; 編譯器生成相同機器碼
++k;
int a = 5, b;
b = a++; // b=5, a=6 (先賦值後遞增)
b = ++a; // b=6, a=6 (先遞增後賦值)
for (int i = 0; i < n; ++i) { } // 風格推薦:無需臨時值,語義清晰
// 編譯器優化後無性能差異,但 ++i 表達「遞增迭代器」意圖
char *src = "hello", *dst = buf;
while (*dst++ = *src++) { } // 複制字符串含 '\0'
// *dst++ 等價 *(dst++):取舊值解引用賦值,指針後移
// k++
mov eax, DWORD PTR [rbp-4] // 載入 k
lea edx, [rax+1] // 計算 k+1
mov DWORD PTR [rbp-4], edx // 存回 k
// 返回值在 eax (舊值)
// ++k
mov eax, DWORD PTR [rbp-4]
add eax, 1
mov DWORD PTR [rbp-4], eax
// 返回值在 eax (新值)
// 現代編譯器優化後,獨立語句生成完全相同代碼
a[i] = i++; — UBprintf("%d %d", i++, i); — UBfunc(i++, i); — UB (參數求值順序未規定)old = k; k++; 或 old = k++; (單一修改);++k; (語義更清晰);-Wsequence-point (GCC/Clang) 可捕獲大多數 UB。