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

C語言 while 循環條件中後置自增陷阱:序列點與副作用順序

     編輯:關於C

經典 C 語言面試題:while(n++ < 10) printf("%d", n); 輸出什麼?直覺以為 0-10,實際輸出 1-10。根因在於 C 標準規定的「序列點」:while 判斷表達式結束即為序列點,**副作用(自增)必須在進入循環體前完成**

代碼與直覺對比

#include 
#define TEN 10

int main() {
    int n = 0;
    while (n++ < TEN)
        printf("%5d", n);
    printf("\n");
    return 0;
}

輸出結果

    1    2    3    4    5    6    7    8    9   10

無 0,從 1 開始,到 10 結束。

標準解析:序列點與副作用

  1. n++ < 10 是 while 的完整判斷表達式。
  2. C 標準規定:**完整表達式結束處是序列點**。
  3. 序列點之前,**所有副作用(如自增)必須完成**;序列點之後,副作用不得開始。
  4. 因此:n++ 的副作用(n 變為 1)在 printf 執行前**已經生效**。
  5. printf 使用的是已自增後的 n。

逐步執行還原

對比:若副作用在循環體後

假設 C 允許「先用後增」延遲到循環體結束:

// 偽碼:錯誤理解
while (n < 10) {
    printf("%d", n);  // 輸出 0
    n++;              // 副作用延遲到這裡
}
// 實際輸出會是 0 1 2 ... 9

但標準**禁止**這種行為,編譯器必須確保副作用在序列點前完成。

前置自增對比

int n = 0;
while (++n < 10)  // 前置自增
    printf("%d", n);
// 輸出:1 2 3 4 5 6 7 8 9
// 判斷用增後值,n=10 時 10<10 偽,循環結束,不輸出 10

最佳實踐建議

  1. 避免在循環條件中使用副作用表達式:可讀性差,易出錯。
  2. 分離判斷與更新:
    for (int n = 1; n <= 10; ++n)  // 清晰、無歧義
        printf("%d", n);
  3. 必須用 while 時:
    int n = 0;
    while (n < 10) {
        ++n;
        printf("%d", n);
    }

總結

while(n++ < 10) 輸出 1-10 而非 0-9,是因為 C 標準序列點規則強制副作用(自增)在進入循環體前完成。這不是編譯器 Bug,而是語言標準保障的確定性行為。理解序列點、副作用順序,是寫出無歧義 C 代碼的關鍵內功。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
輪次判斷前 nn++ < 10 結果副作用後 nprintf 輸出
100<10 真11
211<10 真22
...............
1099<10 真1010
111010<10 假11(循環結束)