switch文でbreakを忘れて次のcaseまで実行される(フォールスルー)
各caseの末尾にbreakが無いと、一致したcase以降のブロックがそのまま次のcaseに流れ込んで実行され続けます。
なぜエラーが出ないのか
出力: Tue
(エラーなし)- Cは何も報告しません。コンパイルも実行も正常に完了するためです
出力: Tue- 実際の挙動 — 期待した結果と食い違っている箇所
見つけ方- エラーが出ないので、出力を目で確かめるか、コードを目で追うしかありません。この種の誤りが最も発見が遅れます
このエラーが出る典型パターン
パターン1
1 #include <stdio.h> 2 3 int main(void) { 4 int day = 2; 5 switch (day) { 6 case 1: 7 printf("Mon\n"); 8 break; 9 case 2: 10 printf("Tue\n"); 11 ^ 12 case 3: 13 printf("Wed\n"); 14 break; 15 } 16 return 0; 17 }
case 2の末尾にbreakが無いため、一致した後もそのままcase 3まで実行が続いてしまいます(フォールスルー)。
直し方: (空) を break; にします。
パターン2
1 #include <stdio.h> 2 3 int main(void) { 4 int score = 2; 5 switch (score) { 6 case 1: 7 printf("low\n"); 8 break; 9 case 2: 10 printf("mid\n"); 11 ^ 12 case 3: 13 printf("high\n"); 14 break; 15 } 16 return 0; 17 }
breakを忘れると、一致したcaseの後のブロックもそのまま実行され続けます。caseは独立したブロックではなく、単なる飛び込み先のラベルです。
直し方: (空) を break; にします。
パターン3
1 #include <stdio.h> 2 3 int main(void) { 4 int level = 1; 5 switch (level) { 6 case 1: 7 printf("A\n"); 8 ^ 9 case 2: 10 printf("B\n"); 11 break; 12 case 3: 13 printf("C\n"); 14 break; 15 } 16 return 0; 17 }
最初のcaseにbreakが無いと、次のcaseのブロックまで巻き込んで実行してしまいます。
直し方: (空) を break; にします。
パターン4
1 #include <stdio.h> 2 3 int main(void) { 4 int grade = 2; 5 switch (grade) { 6 case 1: 7 printf("A\n"); 8 break; 9 case 2: 10 printf("B\n"); 11 ^ 12 case 3: 13 printf("C\n"); 14 break; 15 } 16 return 0; 17 }
case 2の末尾にbreakが無いと、そのままcase 3まで実行が続いてしまいます。
直し方: (空) を break; にします。
パターン5
1 #include <stdio.h> 2 3 int main(void) { 4 int mode = 1; 5 switch (mode) { 6 case 1: 7 printf("start\n"); 8 ^ 9 case 2: 10 printf("run\n"); 11 break; 12 case 3: 13 printf("stop\n"); 14 break; 15 } 16 return 0; 17 }
最初のcaseにbreakが無いと、次のcaseのブロックまで巻き込んで実行してしまいます。
直し方: (空) を break; にします。
よくある誤解
caseは独立したブロックのように見えますが、実際には単なる「飛び込み先のラベル」でしかありません。breakを書かない限り、一致したcase以降は上から下へそのまま実行が続きます(フォールスルー)。これはバグではなくCの言語仕様上の設計であり、意図的に使われることもあります。
実務での勘所
意図的なフォールスルーと書き忘れを区別する手段として、比較的新しいコンパイラは[[fallthrough]]という注釈(C23で標準化、それ以前はGCCの__attribute__((fallthrough))など処理系ごとの拡張として利用可能)をサポートしています。caseの最後にこれを書いておくと、「ここのbreak忘れは意図的です」とコンパイラと読み手の両方に伝えられ、-Wimplicit-fallthroughのような警告オプションを有効にしていても警告されなくなります。