運算符、表達式、語句是C語言程序的三大構建塊。本文梳理核心概念:表達式求值與副作用、順序點語義、語句分類、類型轉換規則、強制轉換用法,助力寫出正確、高效、可維護的C代碼。
a=5 值為5,3+4 值為7); 結尾。表達式加分號即成為表達式語句{ ... } 包裹的多條語句,又稱代碼塊i++ 修改 i,printf 寫標準輸出||、&&、?:、,(逗號運算符)運算符處i = i++;、a[i] = i++;| 優先級 | 運算符 | 結合性 | 說明 |
|---|---|---|---|
| 1 | () [] -> . | 左→右 | 函數調用、下標、成員訪問 |
| 2 | ++ -- + - ! ~ (type) * & sizeof | 右→左 | 後綴/前綴自增減、一元運算、強轉 |
| 3 | * / % | 左→右 | 乘除模 |
| 4 | + - | 左→右 | 加減 |
| 5 | << >> | 左→右 | 移位 |
| 6 | < <= > >= | 左→右 | 關係比較 |
| 7 | == != | 左→右 | 相等比較 |
| 8 | & | 左→右 | 按位與 |
| 9 | ^ | 左→右 | 按位異或 |
| 10 | | | 左→右 | 按位或 |
| 11 | && | 左→右 | 邏輯與(短路) |
| 12 | || | 左→右 | 邏輯或(短路) |
| 13 | ?: | 右→左 | 條件運算符 |
| 14 | = += -= *= /= %= &= ^= |= <<= >>= | 右→左 | 賦值及複合賦值 |
| 15 | , | 左→右 | 逗號運算符(求值序列) |
int i = 5;
int a = ++i; // 前綴:先增後用,a=6, i=6
int b = i++; // 後綴:先用後增,b=6, i=7
// 經典未定義行為:
i = i++; // UB:同一順序點修改i兩次
printf("%d %d", i++, i++); // UB:參數求值順序未規定
a[i] = i++; // UB:讀取i用於下標、又修改i
char、short(有符號/無符號)→ int(或 unsigned int)long doubledoublefloatunsigned long longlong longunsigned longlongunsigned intint(最低)char/short→int,float→double(舊式聲明/無原型時)(type_name) expression // 例: (long) a; // int → long (float) (x / y); // 整除結果轉float(注意:先整除再轉,精度已失) (float) x / y; // x轉float,觸發浮點除法(正確) // 指針轉換需謹慎: void* p = &i; int* pi = (int*)p; // 正確 // 違反嚴格別名規則: float* pf = (float*)&i; // UB:通過float* 訪問int對象
(a & b) | ci++ 不要出現在同一表達式多處,或與對 i 的其他訪問混用-1 > 0u 為真(-1轉無符號變巨大),啟用編譯器警告 -Wsign-comparefabs(a-b) < 1e-9 替代 a==b掌握運算符優先級、副作用/順序點語義、類型轉換階梯,是從「能寫出代碼」進階到「寫出正確、無UB、可移植代碼」的分水嶺。建議將本文優先級表、轉換階梯、UB模式收藏備查,代碼評審時重點檢查副作用衝突與有符號/無符號混用場景。