言語
日本語
English

Caution

お使いのブラウザはJavaScriptが無効になっております。
当サイトでは検索などの処理にJavaScriptを使用しています。
より快適にご利用頂くため、JavaScriptを有効にしたうえで当サイトを閲覧することをお勧めいたします。

C言語辞典

  1. トップページ
  2. C言語辞典
  3. for / while / do-while

for / while / do-while

対応: C89(1989)

同じ処理を繰り返すループ構文です。回数が決まっている繰り返しには『for』、条件が満たされる間繰り返す場合は『while』、最低1回は実行したい場合は『do while』を使います。

構文

// カウンタを使って指定回数繰り返します。
for (初期化; 条件式; 更新) {
    処理;
}

// 条件が真の間繰り返します(条件を先に評価します)。
while (条件式) {
    処理;
}

// 処理を実行してから条件を評価します(最低1回実行されます)。
do {
    処理;
} while (条件式);

// ループを途中で抜けます。
break;

// 残りの処理をスキップして次のループに進みます。
continue;

ループ制御キーワード一覧

キーワード概要
for初期化・条件・更新の3つを一行に書けます。繰り返し回数が決まっている場合に適しています。
while条件が真の間処理を繰り返します。条件が最初から偽の場合、一度も実行されません。
do while処理を実行してから条件を判定します。必ず最低1回は実行されます。
break現在のループまたはswitchを即座に終了します。
continue現在の反復処理の残りをスキップして、次の反復に進みます。

サンプルコード

sample_for_while.c
#include <stdio.h>

int main(void) {
    // for ループで 1 から 5 まで出力します。
    for (int i = 1; i <= 5; i++) {
        printf("%d ", i); // 『1 2 3 4 5 』と出力されます。
    }
    printf("\n");

    // ネストした for ループで九九の一部を出力します。
    for (int i = 1; i <= 3; i++) {
        for (int j = 1; j <= 3; j++) {
            printf("%d*%d=%d ", i, j, i * j);
        }
        printf("\n");
    }

    // while ループで条件が満たされる間繰り返します。
    int n = 1;
    while (n <= 100) {
        n *= 2;
    }
    printf("100を超える最初の2の累乗: %d\n", n); // 『128』と出力されます。

    // do while で少なくとも1回実行します。
    int count = 0;
    do {
        count++;
        printf("count = %d\n", count);
    } while (count < 3); // 3回出力されます。

    // break で条件に合った要素を見つけたらループを抜けます。
    int nums[] = {3, 7, 2, 9, 4};
    for (int i = 0; i < 5; i++) {
        if (nums[i] == 9) {
            printf("9は%d番目にあります。\n", i); // 『9は3番目にあります。』と出力されます。
            break;
        }
    }

    // continue で偶数だけ出力します。
    for (int i = 1; i <= 10; i++) {
        if (i % 2 != 0) continue; // 奇数はスキップします。
        printf("%d ", i); // 『2 4 6 8 10 』と出力されます。
    }
    printf("\n");

    return 0;
}

コンパイルして実行すると次のようになります。

gcc for_while.c -o for_while
./for_while
1 2 3 4 5
1*1=1 1*2=2 1*3=3
2*1=2 2*2=4 2*3=6
3*1=3 3*2=6 3*3=9
100を超える最初の2の累乗: 128
count = 1
count = 2
count = 3
9は3番目にあります。
2 4 6 8 10

無限ループと break / continue

while(1) や for(;;) は意図的な無限ループを表現するイディオムです。break で脱出し、continue で次のイテレーションに進みます。

loop_break_continue.c
#include <stdio.h>

int main(void) {
    int count = 0;
    while (1) {
        count++;
        if (count % 2 == 0) continue;
        if (count > 9) break;
        printf("%d ", count);
    }
    printf("\n");

    for (int i = 1; i <= 20; i++) {
        if (i % 3 == 0) continue;
        if (i > 12) break;
        printf("%d ", i);
    }
    printf("\n");

    return 0;
}

コンパイルして実行すると次のようになります。

gcc loop_break_continue.c -o loop_break_continue
./loop_break_continue
1 3 5 7 9
1 2 4 5 7 8 10 11

ネストしたループと goto によるラベル脱出

C言語では break は直近のループだけを抜けます。多重ループを一度に抜けたい場合は goto を使うパターンがあります。

loop_goto.c
#include <stdio.h>

int main(void) {
    int matrix[3][4] = {
        {1, 2, 3, 4},
        {5, 6, 0, 8},
        {9, 10, 11, 12}
    };
    int found_row = -1, found_col = -1;

    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 4; j++) {
            if (matrix[i][j] == 0) {
                found_row = i;
                found_col = j;
                goto done;
            }
        }
    }
done:
    if (found_row >= 0) {
        printf("0 は [%d][%d] にあります。\n", found_row, found_col);
    } else {
        printf("0 は見つかりませんでした。\n");
    }
    return 0;
}

コンパイルして実行すると次のようになります。

gcc loop_goto.c -o loop_goto
./loop_goto
0 は [1][2] にあります。

よくあるミス

よくあるミス: off-by-one エラー

配列の要素数と for ループの終了条件が合わないと、範囲外アクセスが発生します。

#include <stdio.h>

int main(void) {
    int arr[5] = {10, 20, 30, 40, 50};
    /* NG: i <= 5 は範囲外(arr[5] は存在しない) */
    for (int i = 0; i <= 5; i++) {
        printf("%d\n", arr[i]);
    }
    return 0;
}

arr[5] は範囲外なので不定値またはクラッシュが発生します。

loop_oob_ok.c
#include <stdio.h>

int main(void) {
    int arr[5] = {10, 20, 30, 40, 50};
    int n = sizeof(arr) / sizeof(arr[0]);
    /* OK: i < n(< を使う) */
    for (int i = 0; i < n; i++) {
        printf("%d\n", arr[i]);
    }
    return 0;
}

修正後は次の通りです。

gcc loop_oob_ok.c -o loop_oob_ok
./loop_oob_ok
10
20
30
40
50

概要

C99以降では『for』の初期化部でループカウンタを宣言できます(例:『for (int i = 0; ...)』)。この場合、変数のスコープはループ内に限定されます。

ループの終了条件を間違えると無限ループになります。特に配列のインデックスには注意が必要で、要素数を超えたアクセスは未定義動作を引き起こします。配列サイズのチェックには『sizeof』を活用してください。

『while (1)』や『for (;;)』は意図的な無限ループを表現するイディオムで、『break』と組み合わせてイベントループやサーバーループに使われます。条件分岐との組み合わせについては『if / else』を参照してください。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。