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

C語言前綴遞減 --a 與後綴遞減 a-- 區別詳解:副作用與序列點

     編輯:C 語言問答

核心區別:值的產生時機

運算符名稱表達式值副作用 (變量修改) 完成時機
--a前綴遞減**遞減後**的新值序列點前 (表達式求值前完成)
a--後綴遞減**遞減前**的舊值序列點前 (但值產生在副作用前)

直觀示例

int a = 5;
printf("%d\n", --a);  // 輸出 4,a 變 4
a = 5;
printf("%d\n", a--);  // 輸出 5,a 變 4
printf("%d\n", a);    // 輸出 4

經典陷阱:單語句多次副作用 → 未定義行為 (UB)

int a = 1;
printf("%d %d %d %d\n", a, a++, a, a++);  // ❌ UB!輸出不可預測

C 標準**不規定**參數求值順序、副作用應用順序。不同編譯器、優化等級輸出不同:

  • GCC -O0:3 2 2 1
  • Clang -O2:1 1 1 1
  • MSVC:3 2 2 1

安全準則

  1. 一條語句中,對同一變量最多進行一次副作用操作 (++, --, =, += 等)。
  2. 拆分語句:
    int a = 1;
    int v1 = a;
    int v2 = a++;
    int v3 = a;
    int v4 = a++;
    printf("%d %d %d %d\n", v1, v2, v3, v4);  // 明確定義行為
  3. 函數參數求值順序未規定:func(a++, a++) 同樣 UB,需拆分。

序列點與 C11 「 sequencing 」

  • C99 以「序列點」定義副作用完成時機:語句結尾 ;、&& || ?: , (逗號運算符) 等。
  • C11 引入「sequenced before/after」關係,更精確描述求值順序,但**不改變**上述 UB 結論。

面試常考變體

int a = 10;
int b = --a + a--;  // 如何計算?
// 步驟:--a → a=9, 值=9
//      a-- → 值=9, 然後 a=8
//      b = 9 + 9 = 18
// 最終 a=8, b=18

掌握「值產生時機、副作用完成時機、單語句單副作用」三原則,徹底征服自增自減陷阱。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved