switch 本質是**標籤跳轉表**,匹配 `case` 後**依序向下執行**,直到遇到 `break` 或 `}` 結束。若漏寫 `break`,會**貫穿執行後續 case**。
int x = 1, y = 2, a = 0, b = 0;
switch (x) {
case 1: a++; // 無 break!
case 2: b++; a++; // 會被執行到
}
switch (y) {
case 1: a++;
case 2: b++; a++;
}
printf("a=%d, b=%d\n", a, b); // 輸出 a=4, b=2 (非預期)
switch (x) {
case 1: do_one(); break;
case 2: do_two(); break;
default: do_default(); break; // default 也建議加 break (習慣)
}
switch (month) {
case 3: case 4: case 5: printf("春季\n"); break;
case 6: case 7: case 8: printf("夏季\n"); break;
case 9: case 10: case 11: printf("秋季\n"); break;
case 12: case 1: case 2: printf("冬季\n"); break;
default: printf("無效月份\n");
}
規範**:刻意貫穿處**必須加註解** `/* fallthrough */`,C23 引入 `[[fallthrough]]` 屬性標準化此意圖。
| 陷阱 | 現象 | 修正 |
|---|---|---|
| 漏寫 break | 邏輯錯誤,難除錯 | 養成「寫 case 即寫 break」肌肉記憶 |
| default 無 break | 若 default 不在最後,會貫穿 | default 也加 break,或永遠放最後 |
| case 為變數 | 編譯錯誤 | case 必須為編譯期常數 |
| switch 判斷字串 | 編譯錯誤 | 改用 if-else strcmp 或雜湊表 |
/* GCC/Clang */
-Wimplicit-fallthrough // 警告無註解貫穿
-Wswitch-enum // enum switch 漏列 case
-Wswitch-default // 缺少 default
break 是 `switch` 的**邊界守門員**。除非**刻意且標註**貫穿,**每個 case 結尾必須有 break**。養成習慣、開啟編譯器警告,能消滅 99% 的 switch 貫穿 Bug。