流程控制是程序靈魂所在。C 語言提供 if-else、switch-case 兩大分支結構,看似簡單,實則蘊含豐富的工程細節與優化技巧。本文從語法語義、編譯器實現、最佳實踐三個維度,深度剖析分支控制的核心要點。
if (expression) statement1; else statement2; // 可選
expression 為標量類型(整數、指針、浮點數),非 0 為真,0 為假。else 與最近的未匹配 if 配對(懸空 else 問題)。
if (score >= 90) grade = 'A'; else if (score >= 80) grade = 'B'; else if (score >= 70) grade = 'C'; else if (score >= 60) grade = 'D'; else grade = 'F';
此結構等價於巢狀 if,但可讀性更強。編譯器通常生成條件跳轉指令序列。
// 錯誤:C 不支持鏈式比較 if (0 < x < 100) // 恆真!解析為 (0 < x) < 100 → 0 或 1 < 100 // 正確: if (x > 0 && x < 100)
對於連續、稠密的整數常量案例,現代編譯器(GCC/Clang/MSVC)會將 switch 優化為跳轉表(O(1));稀疏案例則用二分查找(O(log n))。if-else 鏈通常編譯為線性比較跳轉(O(n))。
switch (expression) {
case constant1: statements; break;
case constant2: statements; break;
default: statements; // 可選,位置任意
}
expression 必須為整數類型(含枚舉、字符)case 標簽必須為**整數常量表達式**,不可為變量或範圍break 可省略,形成「貫穿」效果switch (month) {
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
days = 31; break;
case 4: case 6: case 9: case 11:
days = 30; break;
case 2:
days = isLeapYear(year) ? 29 : 28; break;
default:
days = -1; // 錯誤輸入
}
利用貫穿合併多條件,代碼緊湊高效。需在註釋中標註 /* fall through */ 以消除編譯器警告(-Wimplicit-fallthrough)。
Tom Duff 1983 年發明的循環展開技巧,利用 switch 進入循環體中間:
void memcpy_duff(char *to, char *from, size_t count) {
size_t n = (count + 7) / 8;
switch (count % 8) {
case 0: do { *to++ = *from++;
case 7: *to++ = *from++;
case 6: *to++ = *from++;
case 5: *to++ = *from++;
case 4: *to++ = *from++;
case 3: *to++ = *from++;
case 2: *to++ = *from++;
case 1: *to++ = *from++;
} while (--n > 0);
}
}
展現了 switch/case 本質是標簽跳轉,而非結構化塊。
| 場景 | 推薦 | 理由 |
|---|---|---|
| 少量條件(≤3)、複雜表達式、浮點/字符串比較 | if-else | 靈活通用,支持任意標量條件 |
| 多條件、整數/枚舉常量、值分布稠密 | switch | 編譯器優化為跳轉表,O(1) 查找,碼表局部性好 |
| 多條件、值分布稀疏 | switch 或 if-else | 編譯器用二分查找,性能相近,switch 可讀性更好 |
| 需範圍判斷、非常量案例 | if-else | switch 不支持 |
-Wswitch -Wswitch-enum -Wimplicit-fallthroughC23 引入 switch 初始化語句:
switch (int x = get_value(); x) { // 作用域限於 switch 塊
case 1: ...; break;
default: ...;
}
並支持 [[fallthrough]] 標準屬性替代註釋。
分支控制不只是語法糖,更是理解編譯器代碼生成、CPU 分支預測、指令流水線的窗口。善用 switch 的跳表優化,避免 if-else 過長鏈,結合現代編譯器屬性與靜態分析,寫出既高性能又可維護的分支邏輯,是 C 程序員進階的必修課。