C言語学習ポータル(無料版) 学習コンテンツ 制御構造 無限ループとの付き合い方

🔀 制御構造

無限ループとの付き合い方

無料公開版に収録・読む目安 11分

🎯 無限ループの原因を3つの型で診断でき、意図的な無限ループを出口つきで安全に書ける

実行したら、画面が固まって返ってこない。カーソルだけが点滅している。初めてこれに出くわすと「壊した」と思うものですが、たいていは無限ループです。壊れてはいません。怖がるより、原因の型を覚えたほうが早く片付きます。

まず止め方から。実行中のコンソールで Ctrl + C を押せば中断できます。これを知っているだけで恐怖は半分になります。

無限ループの原因は、ほぼ3つの型に収まります。

型1: 更新を忘れた。 whileの中で、条件に使っている変数を動かしていない。

#include <stdio.h>

int main(void) {
    int i = 0;

    while (i < 5) {
        printf("%d ", i);
        // i++;   ← これが無いと 0 が出続ける
    }
    return 0;
}

型2: 更新はしているが、条件に近づかない。 i-- と書くつもりが i++ になっている、i = i + 1 のつもりが i + 1 だけ(計算しても代入していない)、あるいは条件がそもそも絶対に偽にならない(while (x != 3) に対して x が 2 ずつ増えていて 3 を飛び越す、など)。

型3: continueが更新を飛ばした。 前のトピックで見た while + continue の地雷です。

診断のコツは、疑わしいループの先頭に printf を1行入れて、条件に使っている変数の値を毎周表示させること。数字が動いていなければ型1か型3、動いているのに条件に近づかないなら型2です。原因が絞れれば、直すのは一瞬です。

ビット固まっても壊れてないよ。Ctrl+C で止めて、条件の変数がどう動いてるか表示させてみよう

ここまで悪者扱いしてきましたが、わざと終わらせないループもあります。ゲームのメインループ、組み込み機器の制御、サーバーの待ち受け——これらは電源が切れるまで回り続けるのが正しい姿です。

#include <stdio.h>

int main(void) {
    int count = 0;

    while (true) {              // C23 なら true をそのまま書ける
        count++;
        if (count >= 3) {
            printf("3回まわったので終わります\n");
            break;              // 出口は必ず用意する
        }
    }
    return 0;
}

while (true) や for (;;) が定番の書き方です。大事なのは、出口を必ず1つ用意すること。「条件で終わらせない」と決めたなら、代わりに break で終わらせる責任が生じます。出口の無い while (true) は、ただのバグです。

最後に、このトラックの総まとめとして FizzBuzz を書きましょう。1から15まで表示し、3の倍数なら Fizz、5の倍数なら Buzz、両方の倍数なら FizzBuzz にします。

#include <stdio.h>

int main(void) {
    for (int i = 1; i <= 15; i++) {
        if (i % 15 == 0) {
            printf("FizzBuzz\n");
        } else if (i % 3 == 0) {
            printf("Fizz\n");
        } else if (i % 5 == 0) {
            printf("Buzz\n");
        } else {
            printf("%d\n", i);
        }
    }
    return 0;
}

forで回数を決めて回し、if / else ifを狭い条件から並べ、剰余で判定する。このトラックで学んだことが全部入っています。もし i % 3 == 0 を先頭に置いたら、15 は Fizz に吸い込まれて FizzBuzz は一度も表示されません。t06-03 で見た「順番の罠」が、ここでも顔を出すわけです。

ループを書く前のチェックを3つ、置いていきます。この条件は、どの行で偽になる? 条件に使う変数は毎周きちんと動いている? 最悪でも何周で終わる? 3つ目に答えられないループには、安全弁のカウンタを入れておくと安心です。

師範無限ループは失敗ではない。出口を決め忘れただけじゃ。止めて、条件をもう一度読め。それだけのことよ

要点まとめ

アプリで演習問題まで解く(無料・登録不要)

この項目に出てくる用語

無限ループむげんるーぷ

終了条件が満たされることなく、永遠に繰り返され続けてしまうループのこと。意図的に使う場合もあるが、多くはバグとして発生する。for(;;)やwhile(1)のように、あえて意図的に書かれることもある。

while文わいるぶん

条件が真である間、処理を繰り返す構文のこと。何回繰り返すかが実行前には分からない場合に向いた、シンプルな繰り返し構文。条件を書き間違えると、意図せず無限ループになってしまうことがある。

for文ふぉーぶん

「初期化・条件・更新」の3つを1行にまとめて書ける繰り返し構文のこと。回数があらかじめ決まっている繰り返しにとくに向いている。繰り返す回数があらかじめはっきりしている場面で、とくに書きやすい構文。

if文いふぶん

条件が真のときだけ、特定の処理を実行させる制御構造のこと。プログラムの中に「もしも」という分かれ道を作る、いちばん基本の道具。条件が偽のときは何もせず、そのまま次の処理へ進んでいく。

elseえるす

if文の条件が偽だったときに実行する処理を書くための構文のこと。「そうでなければ」という日本語の意味にそのまま対応している。elseの後には条件を書かず、if以外のすべての場合を受け止める役割を持つ。

break文ぶれいくぶん

ループやswitch文の実行をその場で強制的に抜け出す命令のこと。「これ以上繰り返す必要がない」と判断したときに使う。多重ループの中で使うと、いちばん内側のループだけを抜ける点に注意が必要。

continue文こんてぃにゅーぶん

ループの残りの処理を飛ばして、次の繰り返しへすぐ進む命令のこと。特定の条件のときだけ処理をスキップしたい場面で使われる。スキップされるのはあくまで残りの処理であり、ループ自体は終わらない。

同じトラックのほかの項目

流れを変える——制御構造の全体像プログラムの流れが「順次・分岐・繰り返し」の3つでできていることを理解し、場面に応じてどれを使うか見当をつけられ… if文——もしも、の分かれ道if文の書き方と条件式の考え方を理解し、条件によって処理を分けられるようになる else if / else の分かれ道設計else / else if で複数の分かれ道を作れるようになり、範囲判定の順序を正しく設計できる 条件式の罠——= と == の悲劇代入 = と比較 == の違いを説明でき、条件式で取り違えたときに何が起きるかを見抜ける 論理演算子と短絡評価&& || ! で複数の条件を組み立てられるようになり、短絡評価の性質を安全のために利用できる switch文とfallthroughswitch文で値による多分岐を書けるようになり、break忘れによるフォールスルーを理解する for文——回数が決まった繰り返しfor文の3つの部品と実行順序を理解し、回数の決まった繰り返しを正しく書ける while文——条件が決める繰り返しwhile文で終わりの読めない繰り返しを書けるようになり、for との使い分けを判断できる do-while文と入力チェックdo-while の「まず1回は実行する」性質を理解し、入力のやり直しループを書ける breakとcontinueの使いどころbreak でループを打ち切り、continue で残りをスキップできるようになり、それぞれの副作用を避けられる ループのネストと九九表二重ループの動きを説明でき、九九表のような表形式の出力を自分で組み立てられる
‹ ループのネストと九九表

もっと先へ:ポインタ・メモリ・ファイル入出力・セキュアコーディングを含む全26トラックと、段位検定・模試のフルセットは完全版に収録しています。

完全版(BOOTH)を見る

📚 姉妹教材:手を動かして覚える Linux 教材 — Linuxとインフラの仕組みを地図で学ぶ

Web版 / BOOTH