運算符是 C 語言構建表達式的基石。熟練掌握運算符的優先級、結合性、副作用及常見陷阱,能寫出正確、高效、可維護的代碼。本文系統梳理 C 語言所有運算符類別,結合經典面試題與實戰案例,助你攻克運算符難點。
| 類別 | 運算符示例 | 說明 |
|---|---|---|
| 算術運算符 | + - * / % | 基本數學運算,% 僅用於整數 |
| 關係運算符 | == != > < >= <= | 返回 1(真)或 0(假) |
| 邏輯運算符 | && || ! | 短路求值特性 |
| 位運算符 | & | ^ ~ << >> | 操作二進制位,嵌入式開發常用 |
| 賦值運算符 | = += -= *= /= %= | 右結合性,賦值表達式有值 |
| 自增/自減 | ++ -- | 前置/後置區別大,副作用陷阱多 |
| 條件運算符 | ?: | 唯一三目運算符,右結合 |
| 逗號運算符 | , | 最低優先級,求值結果為最後表達式 |
| 指針/成員 | * & -> . | 地址、解引用、結構體成員訪問 |
| sizeof | sizeof(type) | 編譯時計算類型/表達式佔用字節數 |
1. () [] -> . // 函數調用、數組下標、結構體成員(左結合) 2. ! ~ ++ -- + - * & sizeof (type) // 單目運算符(右結合) 3. * / % // 乘除模(左結合) 4. + - // 加減(左結合) 5. << >> // 移位(左結合) 6. < <= > >= // 關係(左結合) 7. == != // 相等性(左結合) 8. & // 按位與(左結合) 9. ^ // 按位異或(左結合) 10. | // 按位或(左結合) 11. && // 邏輯與(左結合,短路) 12. || // 邏輯或(左結合,短路) 13. ?: // 條件運算符(右結合) 14. = += -= *= /= %= // 賦值(右結合) 15. , // 逗號(左結合)
錯誤示例:
int i = 1; int a = i++ + ++i; // 未定義行為!修改 i 兩次無序列點
正確理解:
++i:先增後用,值為增後值i++:先用後增,值為增前值int a = 0, b = 1;
if (a && (b = 2)) { } // b 不會被賦值為 2,因為 a 為 0 直接短路
if (a || (b = 2)) { } // b 會被賦值為 2,因為 a 為 0 需評估右側
利用短路特性可安全檢查指針:if (p && p->next)
C99 規定:a / b 向零截斷,a % b 滿足 (a/b)*b + a%b == a。
-5 / 2 == -2 // 向零截斷 -5 % 2 == -1 // 符號與被除數相同 5 % -2 == 1
int a = 1; double b = 2.0; auto c = a ? a : b; // c 類型為 double,遵循 usual arithmetic conversions
func(a, b, c); // 參數分隔,非逗號運算符,求值順序不定 int x = (a, b, c); // 逗號運算符,順序求值,x = c
int i = 1, j = 2, k = 3; i = j = k = 4; // 右結合:k=4 → j=4 → i=4,整個表達式值為 4
int i = 5, j; j = ++i + i++ + --i; // UB!同一序列點多次修改 i
#define SQUARE(x) x * x int y = SQUARE(3 + 2); // 展開為 3 + 2 * 3 + 2 = 11,非 25 // 正確寫法:#define SQUARE(x) ((x) * (x))
運算符看似基礎,實則暗藏玄機。唯有透徹理解其語義模型,方能在代碼中遊刃有餘,規避隱蔽 Bug。