首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++ 遞增/遞減運算子深度解析:前綴、後綴與複合表達式陷阱

     編輯:關於C++

基礎知識回顧

形式範例運算值副作用時機
前綴 ++++i遞增後的值立即
後綴 ++i++遞增前的值運算值取得後
前綴 ----i遞減後的值立即
後綴 --i--遞減前的值運算值取得後

單一表達式中多個副作用:未定義行為

C++ 標準規定:單一表達式中對同一標量物件進行多次修改,或修改後又存取其值(除非為了計算新值),行為未定義(Undefined Behavior, UB)。編譯器可產生任意結果。

經典陷阱範例

int i = 3;
std::cout << (i++) + (i++) + (i++) << std::endl; // UB!
std::cout << i << std::endl;

// 可能輸出 9, 6(某編譯器:全部取初值 3+3+3=9,語句結束後 i=6)
// 也可能輸出 12, 6(左到右:3+4+5=12)
// 甚至可能輸出其他值或崩潰
切記:不要在單一表達式中對同一變數使用多個 ++/--。這不是「編譯器實作細節」,而是標準明確規定的 UB。

前綴版本同樣 UB

int i = 3;
std::cout << (++i) + (++i) + (++i) << std::endl; // UB!
// 某編譯器:先 i+=3 → i=6,每個 ++i 值為 6 → 18
// 其他編譯器結果不同

混合前綴後綴

int i = 3;
std::cout << (++i) + (i++) + (++i) << std::endl; // UB!
// 某編譯器:先處理兩個前綴 i+=2 → i=5,三項皆取 5 → 15,語句結束 i=6

解析器對 ++i+++i 的處理

++i+++i 經「最大咬合原則」解析為 (++i) ++ + i → ++i 後接 ++(需左值)→ 編譯錯誤:'++' needs l-value。

合法寫法需加空格或括號:

++i + ++i   // 兩個前綴,但同表達式雙修改 → UB
i++ + i     // 合法:i++ 修改,+i 只讀取 → 明確定義
(i++) + i   // 同上,括號明確分組

i+++i 的解析

i+++i → (i++) + i(最大咬合:i++ 是合法後綴運算式)。

i + ++i → i + (++i)。但同表達式修改與存取 i → UB!

輸出串流中的求值順序

int i = 3;
std::cout << i++ << " and " << i++ << std::endl;
// 某編譯器(VC6/VC2005)從右往左求值流運算子參數:
// 右側 i++ → 3,i=4;左側 i++ → 4,i=5 → 輸出 "4 and 3"
// 標準未規定 << 參數求值順序,故結果不可攜帶

最佳實踐總結

  1. 絕不在單一表達式中對同一變數應用多個 ++/--。
  2. 將複雜遞增邏輯拆分為多條語句:++i; sum += i; ++i; sum += i;
  3. 偏好 前綴 ++/--(無暫存物件開銷,語意更清晰)。
  4. 輸出串流鏈式 << 參數求值順序未定義,若相依副作用請分行。
  5. 啟用編譯器警告(-Wall -Wextra -pedantic 或 /W4),可偵測部分 UB 模式。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved