逗號運算符是 C 語言中獨特且常被誤解的運算符。本文詳細解析其求值順序保證、副作用時序、表達式值特性,並通過實例演示常見誤區。
expr1, expr2, expr3, ..., exprN
等價於:((expr1, expr2), expr3), ..., exprN)
int ounces = 0, cost; cost = (ounces++, ounces * 10); // FIRST_OZ = 10 // 等價於: // ounces++; // 副作用:ounces 變為 1 // cost = ounces * 10; // 使用新值計算:1 * 10 = 10 // 整體表達式值 = 10
int houseprice = 239, 500; // 無語法錯誤! // 編譯器視為:houseprice = (239, 500) // 逗號表達式值 = 500 // 實際 houseprice = 500 // 意圖可能是 239500 或 239,500 (不可用逗號分隔數字)

執行結果:

結果證明:a = (b=3, b+2) → b 先賦值 3,再計算 b+2=5,a 最終為 5(右側值)。
| 場景 | 代碼模式 | 說明 |
|---|---|---|
| for 迴圈多變數控制 | for (i=0, j=n; i<j; i++, j--) | 初始化/遞增多變數 |
| 宏定義多語句 | #define SAFE_FREE(p) do { free(p); p=NULL; } while(0) | do-while 包裹,逗號分隔 |
| 函數引數副作用 | func(a++, b++) ❌ 未定義行為 | **引數求值順序未規定**,不可依賴 |
| 變數聲明鏈 | int a=1, b=2, c=3; | 聲明語法,非逗號運算符 |
| 語境 | 性質 | 範例 |
|---|---|---|
| 表達式中 | 運算符 | a = (b=3, b+2) |
| 函數引數列表 | 分隔符 | func(a, b) 求值順序**未定義** |
| 變數聲明 | 分隔符 | int a, b; |
| for 迴圈子句 | 運算符 | for (i=0, j=0; ...; i++, j++) |
x = (a(), b(), c())1,000,000),使用 1000000 或 1'000'000 (C23)C11 §6.5.17:「逗號運算符保證其運算元按從左到右順序求值……左運算元的所有副作用在右運算元求值前完成。逗號表達式的值與型別為其右運算元的值與型別。」
理解逗號運算符的序列點語義,對編寫正確的宏、迴圈控制、以及避免函數引數求值順序陷阱至關重要。記住核心口訣:左邊算完再算右,整體值取最右。