前言:控制流的決策基石
關係運算子比較大小,邏輯運算子組合條件。兩者結果均為 int:真 = 1,假 = 0。理解優先級、短路求值、真假定義,是寫出正確條件判斷的關鍵。
一、邏輯運算子
| 運算子 | 名稱 | 語義 | 短路求值 |
&& | 邏輯 AND | 兩操作數皆非零 → 1 | 左側為 0 時不評估右側 |
|| | 邏輯 OR | 任一操作數非零 → 1 | 左側非 0 時不評估右側 |
! | 邏輯 NOT | 操作數為 0 → 1,否則 0 | 單目,無短路 |
二、關係運算子
| 運算子 | 名稱 | 範例 | 結果 |
> | 大於 | 100 > 99 | 1 |
>= | 大於等於 | 10 >= 10 | 1 |
< | 小於 | 10 < 12 | 1 |
<= | 小於等於 | 5 <= 5 | 1 |
== | 等於 | 5 == 5 | 1 |
!= | 不等於 | 5 != 3 | 1 |
三、真假定義:C 語言的布林觀
- 假:唯一值 0 (整數 0、空指標
NULL、浮點數 0.0、字元 '\0')
- 真:任何非零值 (1、-1、100、非空指標、'A')
- 關係/邏輯運算式結果:真 → 1,假 → 0 (標準化)
四、優先級與結合性 (高到低)
| 優先級 | 運算子 | 結合性 |
| 1 (最高) | () [] . -> ++ -- (後綴) | 左→右 |
| 2 | ++ -- (前綴) + - (一元) ! ~ (型別) * & sizeof | 右→左 |
| 3 | * / % | 左→右 |
| 4 | + - (二元) | 左→右 |
| 5 | << >> | 左→右 |
| 6 | < <= > >= | 左→右 |
| 7 | == != | 左→右 |
| 8 | & (位元 AND) | 左→右 |
| 9 | ^ (位元 XOR) | 左→右 |
| 10 | | (位元 OR) | 左→右 |
| 11 | && (邏輯 AND) | 左→右 |
| 12 | || (邏輯 OR) | 左→右 |
| 13 | ?: (條件運算子) | 右→左 |
| 14 | = += -= ... | 右→左 |
| 15 (最低) | , (逗號運算子) | 左→右 |
五、經典優先級陷阱
// 範例:!1 && 0
// 解析:(!1) && 0 → 0 && 0 → 0
// 若誤解為 !(1 && 0) → !0 → 1 (錯誤)
// 範圍:x > 0 && x < 100
// 正確:(x > 0) && (x < 100) // 關係 > 邏輯,自然正確
// 位元 vs 邏輯優先級
x & 1 == 0 // 錯誤:x & (1 == 0) → x & 0
(x & 1) == 0 // 正確
六、短路求值實戰價值
1. 空指標防護
if (ptr != NULL && ptr->data > 0) // ptr 為 NULL 時不解參考
process(ptr->data);
2. 避免除零
if (denom != 0 && num / denom > 10) // denom 為 0 時不執行除法
...
3. 條件副作用執行
if (init() && start() && run()) // 任一失敗(返回0)立即停止後續
success();
七、常見錯誤
| 錯誤 | 代碼 | 問題 | 修正 |
== 誤寫 = | if (a = 5) | 賦值而非比較,恆真 | if (a == 5) 或 if (5 == a) (編譯器報錯若誤寫) |
| 邏輯運算用位元運算 | if (a & b) | 位元 AND,非邏輯 AND | if (a && b) |
| 浮點數直接比較 == | if (f == 1.0) | 精度誤差導致誤判 | if (fabs(f - 1.0) < EPS) |
| 鏈式比較 | if (0 < x < 10) | 解析為 (0 < x) < 10 恆真 | if (0 < x && x < 10) |
結語
關係與邏輯運算子構成程式決策的骨架。內化「真=非零、假=零、關係>邏輯優先級、短路求值左→右、!=與=嚴格區分」五大核心,並善用短路特性進行防護性檢查,能寫出無邏輯 Bug、高可讀性的條件判斷代碼。