C言語を学び始めると、ループやswitch文で必ず登場するのがbreakとcontinueです。
同じような場所で使われるため混同しやすい一方で、動作はまったく異なります。
本記事では、両者の違いと使いどころを丁寧に整理しながら、典型的な間違いパターンまで詳しく解説していきます。
C言語のbreakとcontinueとは
breakとcontinueの基本的な意味
breakとcontinueは、どちらも「通常の流れを途中で変える」ためのキーワードです。
しかし、どこまで処理を止めるかが大きく異なります。

breakは「今いるループやswitch文そのものを途中で終了する命令」です。
for文やwhile文、do-while文、switch文の内部で利用でき、実行されるとそのブロックから即座に抜け出します。
一方、continueは「今の1回分のループ処理だけを打ち切り、次の繰り返しに進む命令」です。
for文やwhile文などのループ内でのみ利用でき、switch文では使えません。
continueが実行されると、残りの処理をスキップして、次のループ開始処理へ移ります。
ここで大切なのは、breakは「ループ/switch自体を終わらせる」、continueは「1回分の途中を飛ばす」という違いです。
ループ(for/while)でのbreakとcontinueの動き
ループの中でbreakとcontinueがどのように動作するのか、for文を例に確認します。

具体的なサンプルコードを見てみます。
#include <stdio.h>
int main(void) {
// 1〜10の数字を順に表示します
// 5になったら break でループを終了します
for (int i = 1; i <= 10; i++) {
if (i == 5) {
printf("i = %d のときに break します\n", i);
break; // ここで for ループ自体が終了します
}
printf("i = %d\n", i);
}
printf("for ループを抜けました\n");
// もう一度 1〜10 を回しますが、
// 今度は 5 のときだけ continue して表示をスキップします
for (int i = 1; i <= 10; i++) {
if (i == 5) {
printf("i = %d のときに continue します\n", i);
continue; // 残りの処理を飛ばして次の i へ
}
printf("i = %d\n", i);
}
return 0;
}
i = 1
i = 2
i = 3
i = 4
i = 5 のときに break します
for ループを抜けました
i = 1
i = 2
i = 3
i = 4
i = 5 のときに continue します
i = 6
i = 7
i = 8
i = 9
i = 10
この例から分かるように、breakはループ全体を強制終了しますが、continueはその周だけをスキップしてループを継続します。
switch文におけるbreakの役割
switch文では、breakはほぼ必須のキーワードです。
breakを書き忘れると、意図せず次のcaseに処理が「落ちて」進んでしまうので注意が必要です。

簡単なswitch文の例を確認します。
#include <stdio.h>
int main(void) {
int menu = 2;
printf("menu = %d のときの switch 文の例\n", menu);
switch (menu) {
case 1:
printf("メニュー1が選択されました\n");
break; // ここで switch 文を抜けます
case 2:
printf("メニュー2が選択されました\n");
break; // ここで switch 文を抜けます
case 3:
printf("メニュー3が選択されました\n");
break;
default:
printf("不正なメニュー番号です\n");
break;
}
printf("switch 文を抜けました\n");
return 0;
}
menu = 2 のときの switch 文の例
メニュー2が選択されました
switch 文を抜けました
このように、switch文におけるbreakは「そのcaseの処理を終えたらswitch全体から抜ける」ためのものです。
continueはswitch文の中では使えないことも、後ほど詳しく説明します。
breakの使いどころと注意点
無限ループからの脱出に使うbreakの書き方
C言語では、無限ループとbreakを組み合わせて柔軟な繰り返し処理を書くことがよくあります。
典型的なパターンはwhile (1)やfor (;;)とbreakの組み合わせです。

サンプルとして、ユーザーからの入力を受け取り、特定の文字で終了するプログラムを示します。
#include <stdio.h>
int main(void) {
char c;
printf("文字を入力してください。(q で終了)\n");
// while(1) を使った無限ループ
while (1) {
printf("入力: ");
if (scanf(" %c", &c) != 1) {
// 入力エラー時もループ終了
printf("入力エラーのため終了します。\n");
break;
}
if (c == 'q') {
printf("'q' が入力されたのでループを終了します。\n");
break; // 無限ループから抜ける
}
printf("あなたが入力した文字: %c\n", c);
}
printf("プログラムを終了します。\n");
return 0;
}
このように、終了条件をif+breakで書くと、複雑な条件でも柔軟に対応できます。
switch文でbreakを入れ忘れたときの挙動
switch文でbreakを入れ忘れると、次のcaseの処理までそのまま実行されるという挙動(cst-code>fall throughと呼ばれます)になります。
これを知らないとバグの原因になります。

例として、breakを入れ忘れた場合の挙動を見てみます。
#include <stdio.h>
int main(void) {
int rank = 2;
printf("rank = %d のときの switch 文 (break なしの例)\n", rank);
switch (rank) {
case 1:
printf("Gold\n");
// break を忘れている
case 2:
printf("Silver\n");
// break を忘れている
case 3:
printf("Bronze\n");
// break を忘れている
default:
printf("Other\n");
}
return 0;
}
rank = 2 のときの switch 文 (break なしの例)
Silver
Bronze
Other
rankが2にもかかわらず、Silver → Bronze → Otherとすべて表示されています。
これは、case 2に入ったあとbreakがないため、そのまま下のcase 3、defaultへと処理が進んでしまったからです。
逆に、意図的に複数のcaseをまとめて処理したい場合には、あえてbreakを書かないというテクニックも存在します。
// rank が 1 または 2 のときは「上位ランク」としたい例
switch (rank) {
case 1:
case 2:
printf("上位ランクです\n");
break;
default:
printf("その他のランクです\n");
break;
}
このように、breakの有無によって挙動が大きく変わるので、意図しているかどうかを常に意識して書くことが重要です。
多重ループでのbreakの効き方
多重ループ(ネストされたforやwhile)では、breakは「今いる一番内側のループ」にしか効かないという点に注意する必要があります。

次の例で挙動を確認します。
#include <stdio.h>
int main(void) {
// 2重ループの中で break を使う例
for (int i = 1; i <= 3; i++) { // 外側ループ
for (int j = 1; j <= 5; j++) { // 内側ループ
if (j == 3) {
printf("i = %d, j = %d で break\n", i, j);
break; // 内側ループだけを抜ける
}
printf("i = %d, j = %d\n", i, j);
}
printf("外側ループ i = %d が 1回終了\n", i);
}
return 0;
}
i = 1, j = 1
i = 1, j = 2
i = 1, j = 3 で break
外側ループ i = 1 が 1回終了
i = 2, j = 1
i = 2, j = 2
i = 2, j = 3 で break
外側ループ i = 2 が 1回終了
i = 3, j = 1
i = 3, j = 2
i = 3, j = 3 で break
外側ループ i = 3 が 1回終了
このように、breakは常に「最も内側の1つのループ」だけから抜けるという動作になります。
外側のループごと完全に抜けたい場合は、後述するラベル付きbreak(goto)などの手法を検討します。
ifとbreakの組み合わせで処理を早期終了する
ループの中で「特定の条件を満たした時点で、これ以上処理を続ける意味がない」といった場面では、if文とbreakを組み合わせて早期終了することで、処理時間を短縮できます。

例えば、配列の中から特定の値を探す線形探索では、見つかった瞬間にループを終えるのが効率的です。
#include <stdio.h>
int main(void) {
int data[] = {3, 8, 2, 7, 5};
int size = sizeof(data) / sizeof(data[0]);
int target = 7;
int found_index = -1;
// data 配列の中から target を探します
for (int i = 0; i < size; i++) {
if (data[i] == target) {
found_index = i;
// 見つかったのでこれ以上探す必要はありません
break;
}
}
if (found_index != -1) {
printf("値 %d はインデックス %d で見つかりました。\n", target, found_index);
} else {
printf("値 %d は配列内に見つかりませんでした。\n", target);
}
return 0;
}
このような「条件を満たしたらbreak」パターンは、多くのアルゴリズムで使われる典型的な書き方です。
continueの使いどころと注意点
ループの一部処理をスキップするcontinueの使い方
continueは、ループ内の「残りの処理」を飛ばして、次の繰り返しへ進むために使います。
これにより、条件によって「この周はここから先はやらない」といった制御が簡単に書けます。

例として、1〜10のうち偶数だけ処理し、奇数はスキップするコードを示します。
#include <stdio.h>
int main(void) {
printf("1〜10 のうち偶数だけ表示します。\n");
for (int i = 1; i <= 10; i++) {
if (i % 2 == 1) {
// i が奇数のときは、この周の残り処理をスキップ
continue;
}
// ここに来るのは i が偶数のときだけ
printf("偶数: %d\n", i);
}
return 0;
}
1〜10 のうち偶数だけ表示します。
偶数: 2
偶数: 4
偶数: 6
偶数: 8
偶数: 10
このように、continueを使うと「特定の条件のときだけ、この先の処理を行う」構造がすっきり書けるようになります。
for文でのcontinueとインクリメント処理の順番
for文は初期化; 条件; インクリメントという3つの部分から成り立っています。
continueを使ったときに、インクリメント処理がいつ実行されるかは重要なポイントです。

for文の流れは次のようになります。
- 初期化
- 条件判定(偽ならループ終了)
- 本体を実行
- インクリメント処理
- 2に戻る
continueが本体の途中で実行されると、残りの本体はスキップされるが、インクリメント処理は必ず実行されます。
#include <stdio.h>
int main(void) {
for (int i = 0; i < 5; i++) {
if (i == 2) {
printf("i = %d で continue\n", i);
continue; // ここで本体の残りをスキップ
}
printf("本体の処理 i = %d\n", i);
}
return 0;
}
本体の処理 i = 0
本体の処理 i = 1
i = 2 で continue
本体の処理 i = 3
本体の処理 i = 4
この例から分かるように、continueの後でもiはしっかりインクリメントされているため、ループが先へ進みます。
while文でcontinueを使うときの無限ループ注意点
while文でcontinueを使うときに起こりやすいのが、インクリメントをし忘れて無限ループになるというミスです。
for文とは違い、while文ではインクリメントを自分で書く必要があるためです。

誤った例を先に示します。
#include <stdio.h>
int main(void) {
int i = 0;
// このコードには問題があります
while (i < 5) {
if (i == 2) {
printf("i = %d で continue (誤った例)\n", i);
continue; // i を増やさずに continue してしまう
}
printf("i = %d\n", i);
i++; // インクリメント
}
return 0;
}
このコードは、i が 2 になったときに無限ループになります。
なぜなら、iが2のときにcontinueしてしまうと、i++の行が実行されないため、iはずっと2のままになってしまうからです。
正しい書き方の一例は次のようになります。
#include <stdio.h>
int main(void) {
int i = 0;
while (i < 5) {
if (i == 2) {
printf("i = %d で continue (正しい例)\n", i);
i++; // 先にインクリメントしてから continue
continue;
}
printf("i = %d\n", i);
i++; // インクリメント
}
return 0;
}
i = 0
i = 1
i = 2 で continue (正しい例)
i = 3
i = 4
このように、while文でcontinueを使うときは、ループ変数の更新タイミングに特に注意が必要です。
continueと条件分岐(if)の書き方のコツ
continueを多用すると、「やらない条件」を先に書いてどんどんスキップするスタイルになります。
これをうまく使うと、ネストの浅い読みやすいコードを書けます。

例えば、複数条件を満たした要素だけを処理したいとき、次の2パターンを比べてみます。
ネストが深い例:
for (int i = 0; i < n; i++) {
if (is_valid(a[i])) {
if (a[i] > 0) {
if (a[i] % 2 == 0) {
// 条件をすべて満たしたときの処理
}
}
}
}
continueを使ってガード節にした例:
for (int i = 0; i < n; i++) {
if (!is_valid(a[i])) {
continue;
}
if (a[i] <= 0) {
continue;
}
if (a[i] % 2 != 0) {
continue;
}
// ここに来た時点で、すべての条件を満たしている
// 条件をすべて満たしたときの処理
}
後者の方が、「満たしていない場合は早めに抜ける」という流れがはっきりしていて読みやすいことが多いです。
breakとcontinueで間違えやすいケース
breakとcontinueの違いを取り違える典型例
初心者がよくやってしまうのが、「ここはループを抜けたい」のにcontinueを書いてしまう、またはその逆というミスです。

次のような例を考えます。
負の値が入力されたら入力処理をやめたい場合、本来はbreakを使うべきです。
#include <stdio.h>
int main(void) {
int n;
while (1) {
printf("正の整数を入力してください。(負の値で終了)\n");
scanf("%d", &n);
if (n < 0) {
// ここで continue と書いてしまうと…
// continue; // 間違った書き方
break; // 正しいのはこちら
}
printf("入力された値は %d です。\n", n);
}
printf("入力処理を終了しました。\n");
return 0;
}
ここで間違えてcontinueを書いてしまうと、負の値を入力してもループが終わらず、延々と入力を求め続けることになります。
「ループ全体を終えたいのか」「この1回分だけスキップしたいのか」を常に意識することが重要です。
switchの中でcontinueを使えない理由
C言語では、switch文の中でcontinueを書くとコンパイルエラーになります。
continueは「ループの次の繰り返しへ進む」ためのキーワードであり、switch文自体はループではないからです。

誤ったコード例を示します。
#include <stdio.h>
int main(void) {
int i = 1;
switch (i) {
case 1:
printf("case 1\n");
continue; // コンパイルエラーになる
default:
printf("default\n");
break;
}
return 0;
}
このコードは、「continue文の対象となる反復文が存在しません」といったエラーになります。
ただし、switchがループの中に書かれている場合、switchの中にあるcontinueは「そのループに対するcontinue」として解釈されます。
例えば次のようなコードは有効です。
#include <stdio.h>
int main(void) {
for (int i = 0; i < 3; i++) {
int n = i % 2;
switch (n) {
case 0:
printf("i = %d は偶数\n", i);
break; // switch を抜ける
case 1:
printf("i = %d は奇数なので、この周の残り処理をスキップ\n", i);
continue; // for ループの次の周へ
}
// n が 0 (偶数) のときだけ実行される処理
printf("偶数のときだけ行う追加処理 i = %d\n", i);
}
return 0;
}
i = 0 は偶数
偶数のときだけ行う追加処理 i = 0
i = 1 は奇数なので、この周の残り処理をスキップ
i = 2 は偶数
偶数のときだけ行う追加処理 i = 2
ここでは、continueはforループに対して効いている点がポイントです。
ラベル付きbreak(goto)と混同しやすいケース
C標準自体には「ラベル付きbreak」はありませんが、「外側のループまで一気に抜けたい」ときにgotoで似たような動作を実現することがあります。
このため、「breakでどこまで抜けられるのか」が混乱しやすくなります。

次のコードは、gotoで多重ループを一気に抜ける例です。
#include <stdio.h>
int main(void) {
int found_i = -1, found_j = -1;
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (i * j == 6) {
found_i = i;
found_j = j;
// 多重ループ全体から抜けたいので goto を使用
goto END_SEARCH;
}
}
}
END_SEARCH:
if (found_i != -1) {
printf("i * j = 6 となる組み合わせ: i = %d, j = %d\n", found_i, found_j);
} else {
printf("条件を満たす組み合わせは見つかりませんでした。\n");
}
return 0;
}
i * j = 6 となる組み合わせ: i = 2, j = 3
この例は分かりやすいものの、gotoは乱用するとコードが読みにくくなりやすいという欠点があります。
C++など他の言語にはラベル付きbreak構文を持つものもありますが、C言語標準には存在しないため、break自体は常に1段階だけ抜けると覚えておくと混乱しにくくなります。
ネストが深いループでのbreak/continueの読みづらさ対策
ループのネストが深くなると、どのbreakやcontinueがどのループに効いているのかが分かりづらくなってきます。
読みやすさのために、いくつかの工夫が有効です。

対策として、次のような方法があります。
1つ目は、コメントで「どのループに対するbreak/continueなのか」を明示する方法です。
for (int i = 0; i < 10; i++) { // 外側ループ
for (int j = 0; j < 10; j++) { // 中間ループ
for (int k = 0; k < 10; k++) { // 内側ループ
if (条件A) {
// 内側ループを抜ける
break; // break inner-loop (k ループ)
}
if (条件B) {
// 中間ループを抜けたい場合は工夫が必要
// (フラグを立てて外側で break する、など)
}
}
}
}
2つ目は、処理を関数に切り出すことで、1つの関数の中でのネストの深さを抑える方法です。
#include <stdbool.h>
bool process_inner_loop(int i) {
for (int j = 0; j < 10; j++) {
if (/* ある条件 */) {
return true; // 特別な状態を通知して「事実上の多重 break」
}
}
return false;
}
int main(void) {
for (int i = 0; i < 10; i++) {
if (process_inner_loop(i)) {
// 内側の処理から「やめたい」という合図が来たので外側も終了
break;
}
}
return 0;
}
このように、ネストが深くなるほど、break/continueを減らし、処理を分割して見通しを良くすることが大切です。
まとめ
breakとcontinueは、どちらも「通常の流れを変える」キーワードですが、breakはループやswitchそのものを終了し、continueはその周の残り処理だけをスキップする点が決定的に異なります。
特に、switch文でのbreak忘れや、while文+continueでのインクリメント忘れ、多重ループでの対象ループの勘違いなどは典型的な落とし穴です。
目的が「ループ全体を終わらせたいのか」「この1回分だけ飛ばしたいのか」を常に意識しながら書けば、breakとcontinueを安全かつ効果的に使いこなせるようになります。
