在 C 語言中,**任何標量類型(整數、浮點、指針)在邏輯判斷上下文中,值為 0 視為「假」,非 0 視為「真」**。因此:
if (i) {
// 當 i != 0 時執行
}
// 完全等價於
if (i != 0) {
// 當 i != 0 時執行
}
| 類型 | 「假」值 | 「真」值示例 | 典型場景 |
|---|---|---|---|
整數(int、char、long 等) | 0 | 1、-1、42 | 計數器、標誌位、返回碼 |
浮點數(float、double) | 0.0 | 1.0、-3.14、1e-10 | 閾值比較、物理量判斷 |
指針(T*、void*) | NULL(即 (void*)0) | 合法地址、&var、malloc() 返回值 | 空指針檢查、資源有效性 |
int *p = malloc(n * sizeof(int));
if (p) { // 等價於 if (p != NULL)
// 安全使用 p
} else {
// 分配失敗處理
}
int rc = do_something();
if (rc) { // 非 0 表示錯誤(約定俗成)
handle_error(rc);
}
// 或:成功返回 0,失敗返回非 0
if (!do_something()) { // 成功時執行
// ...
}
_Bool/bool 之前的慣用法)int flag = 0;
if (condition) flag = 1;
if (flag) { ... } // 清楚表達「若標誌置位則執行」
現代建議:C99 起包含 <stdbool.h> 使用 bool、true、false,語義更清晰。
char *str = get_string();
if (str && *str) { // 指針非空且首字符非 '\0'
process(str);
}
| 陷阱代碼 | 問題 | 修正 |
|---|---|---|
if (p = malloc(...)) | 賦值而非比較,極易誤寫 | 分兩行:p = malloc(...); if (p) 或啟用 -Wparentheses 警告 |
if (str == "abc") | 比較指針而非字符串內容 | 用 strcmp(str, "abc") == 0 |
if (fp = fopen(...)) | 同上,賦值隱患 | 分離賦值與判斷 |
if (x = 5) | 常量賦值,永遠為真 | 習慣寫 if (5 == x)(Yoda 條件)或依賴編譯器警告 |
| 浮點數直接判斷 | 精度誤差導致非預期真/假 | 用 fabs(x) < EPS 判斷「接近零」 |
if (p && *p) 若 p==NULL 則不會求值 *p,安全訪問。if (x) 優化為測試條件碼 test reg, reg; jnz label,極高效。if (signed_overflow)、if (uninitialized_var) 導致 UB,現代編譯器(GCC/Clang -fsanitize=undefined)可捕獲。if (ptr) / if (!ptr),簡潔慣用。if (rc) 表示失敗,if (!rc) 表示成功,文檔註明約定。bool、true、false,禁用 int 模擬。bool is_valid(const T* p),提升可讀性。if (NULL == ptr) 可防誤寫賦值,但現代編譯器警告已足夠,團隊統一即可。if(i) 是 C 語言「非零即真」哲學的核心體現:簡潔、高效、慣用。掌握其在指針、整數、浮點、返回碼等場景的語義與陷阱,配合 stdbool.h、編譯器警告、靜態分析工具,能寫出既地道又安全的條件判斷代碼。**記住:指針判空用 `if(p)`,錯誤碼判失敗用 `if(rc)`,布爾邏輯用 `bool`**。