運算符優先級決定表達式的「隱式括號」,搞錯優先級是 C 語言邏輯 Bug 的高發區。本文提供**標準 15 級優先級完整表**、**經典順口溜**、**結合性規則**、**實戰易錯案例**與**編譯器輔助技巧**,讓你徹底告別「加不加括號」的猶豫。
| 級別 | 運算符 | 說明 | 結合性 |
|---|---|---|---|
| 1 | () [] . -> |
括號、下標、成員訪問 (對象/指針) | **左→右** |
| 2 | ! ~ + - ++ -- & * (type) sizeof |
邏輯非、按位取反、正負號、前置遞增減、取地址、解引用、強轉、長度 | |
| 3 | * / % |
乘、除、取模 | |
| 4 | + - |
加、減 | |
| 5 | << >> |
左移、右移 | |
| 6 | < <= > >= |
關系運算符 | |
| 7 | == != |
相等、不等 | |
| 8 | & |
按位與 | |
| 9 | ^ |
按位異或 | |
| 10 | | |
按位或 | |
| 11 | && |
邏輯與 (短路) | |
| 12 | || |
邏輯或 (短路) | |
| 13 | ?: |
條件運算符 (三目) | **右→左** |
| 14 | = += -= *= /= %= &= ^= |= <<= >>= |
賦值及複合賦值 | **右→左** |
| 15 | , |
逗號運算符 (順序求值,取最後值) | **左→右** |
括號成員第一; // () [] . ->
全體單目第二; // ! ~ + - ++ -- & * (type) sizeof
乘除余三,加減四; // * / % → + -
移位五,關系六; // << >> → < <= > >=
等於不等排第七; // == !=
位與異或和位或; // & → ^ → | ("三分天下" 八九十)
邏輯與跟邏輯或; // && → || (十二和十一,注意順序!)
條件高於賦值, // ?: (13) > = (14)
逗號運算級最低! // , (15)
++/--、+/- (正負)、&/* (取址/解引用)、sizeof 都在這裡,比乘除高。& (8) < == (7) < && (11) < || (12)。a & b == c 實為 a & (b == c),**極易錯**,必加括號。a = b ? c : d 實為 a = (b ? c : d)。a = (b, c) 先算 b 再算 c 賦給 a。| 錯誤表達式 | 實際解析 (隱式括號) | 預期邏輯 | 正確寫法 |
|---|---|---|---|
a & b == c |
a & (b == c) |
(a & b) == c |
(a & b) == c |
*p++ |
*(p++) (後綴++最高) |
(*p)++ (遞增值) |
(*p)++ |
sizeof int * p |
(sizeof int) * p |
sizeof (int *p) |
sizeof(int) * p 或 sizeof(*p) |
a = b = c = 1 |
a = (b = (c = 1)) (右結合) |
鏈式賦值 | 正確 (右結合天然支持) |
a ? b : c = d |
a ? b : (c = d) (三目>賦值) |
(a ? b : c) = d |
(a ? b : c) = d (需加括號) |
f() + g() * h() |
f() + (g() * h()) |
同上 | 正確 (但調用順序未定,若有副作用需分語句) |
// GCC/Clang
-Wparentheses // 警告建議加括號的表達式 (如 a & b == c)
-Wsequence-point // 警告未定義求值順序 (如 i = i++)
-Wlogical-op // 警告邏輯運算符可能混淆 (如 || 用作 &&)
// 開啟建議
gcc -Wall -Wextra -Wparentheses -Wsequence-point -Wlogical-op ...
// Clang 更強
clang -Weverything -Wno-c++98-compat ...
(a & b) == c 零開銷,可讀性 +100。#define SQR(x) ((x)*(x))。15 級優先級、3 類右結合、1 條順口溜。**核心不在背誦,在「不確定即加括號」的工程習慣**。現代編譯器 -Wparentheses 已能捕獲 90% 優先級隱患。將精力投入到**算法設計、架構抽象、測試覆蓋**上,才是高效程序員的正道。