閉じる

C言語のfor文とは?初期化・条件・更新の順番をわかりやすく

for文は定型的な繰り返し処理を1行にまとめて書けるC言語の基本構文です。

本記事では初期化・条件・更新の順番から基本パターン、注意点、while文との使い分けまで、入門者がつまずきやすい点を段階的に解説します。

実行例を交え、真似しやすい形で理解を固めていきます。

for文とは?

for文の役割と使いどころ

for文は、回数が明確な繰り返しに最適な構文です。

配列の全要素を処理したり、同じ処理を一定回数だけ繰り返したいときに読みやすく、間違いを防ぎやすい書き方ができます。

初期化、継続条件、カウンタの更新がヘッダにまとまるため、ループの意図が一目でわかるのが特徴です。

初期化・条件・更新の順番

for文は次の順番で実行されます。

  1. 初期化を最初に1回だけ評価します。
  2. 条件を評価し、真(非0)なら本体を実行、偽(0)ならループを終了します。
  3. 本体を実行し終えたら更新を評価します。
  4. ふたたび条件の評価に戻ります。

したがって、更新は各反復の末尾で実行され、条件は反復の先頭で毎回評価されます。

for文の構文(書き方)

C言語の一般形は次の通りです。

C言語
/* 一般形(概念)
   for (初期化; 条件; 更新) {
       // 繰り返したい処理(0回以上繰り返される)
   }
*/

各部は任意で、省略することもできます。

例えば、初期化や更新を空にすれば、ヘッダ以外に書いた処理が使われます。

条件を省略すると常に真となり無限ループになります。

初期化の書き方と変数スコープ

C99以降では、forの初期化部でループ変数を宣言できます。

宣言した変数はループのスコープ(波括弧の内側)でのみ有効です。

C言語
// C99以降: ループ内だけでiが見える
for (int i = 0; i < 5; i++) {
    /* iはここで使える */
}
/* ここではiは見えない(スコープ外) */

ループの外でも変数を使いたい場合や、C90準拠の古いコンパイラでは、先に宣言してから使います。

C言語
int i;                 // 先に宣言
for (i = 0; i < 5; i++) {
    /* ... */
}
printf("%d\n", i);     // ここでもiが使える

なお、複数の変数を初期化するにはカンマ演算子が使えます。

C言語
for (int i = 0, j = 10; i < j; i++, j--) {
    // iは増加、jは減少
}

条件式の作り方

条件式は「続けるかどうか」を決める部分で、典型的には比較演算子(<, <=, >, >=, ==, !=)を使います。

配列の要素数がnなら、インデックスは0からn-1が有効範囲なので i < n と書くのが安全で読みやすい定石です。

代入演算子=と等値比較==の取り違えに注意してください。

また、Cでは0が偽、それ以外が真です。

例えばポインタpがNULLでない間繰り返すなら、for (; p; p = p->next) { ... } のように簡潔に書けます。

更新の書き方(インクリメント/デクリメント)

更新では、ループ変数を進めます。

最もよく使うのは次の書き方です。

  • 1ずつ増やす: i++ または ++i
  • 1ずつ減らす: i-- または --i
  • 任意の幅で増やす/減らす: i += 2, i -= 3 など

for文の更新部では i++++i の挙動差は実質ありません。

式の値を使わず副作用だけが必要だからです。

可読性を優先して一貫したスタイルを選びましょう。

for文の使い方(基本パターンと例)

0からn-1までのカウンタループ

最も頻出するパターンです。

配列や文字列の走査にも直結します。

C言語
#include <stdio.h>

int main(void) {
    int n = 5;

    // 0,1,2,3,4 と5回繰り返す
    for (int i = 0; i < n; i++) {
        printf("%d ", i);  // iは0からn-1
    }
    printf("\n");
    return 0;
}
実行結果
出力例:
0 1 2 3 4

降順ループ(逆順)

大きい値から小さい値へ進めたいときはデクリメントを使います。

符号なし型では書き方に注意が必要です。

C言語
#include <stdio.h>
#include <stddef.h>

int main(void) {
    int n = 5;

    // 符号付きintを使った降順
    printf("signed: ");
    for (int i = n - 1; i >= 0; i--) {
        printf("%d ", i);
    }
    printf("\n");

    // 符号なし(size_t)での安全な降順
    // i >= 0 は常に真になるので使わない
    size_t m = 5;
    printf("size_t: ");
    for (size_t i = m; i-- > 0; ) { // iをデクリメントした結果が0より大きい間
        printf("%zu ", i);
    }
    printf("\n");
    return 0;
}
実行結果
出力例:
signed: 4 3 2 1 0
size_t: 4 3 2 1 0

ステップ幅の指定(i+=2など)

偶数だけ、3刻みなど任意のステップで進められます。

C言語
#include <stdio.h>

int main(void) {
    // 偶数だけを列挙
    printf("step 2: ");
    for (int i = 0; i < 10; i += 2) {
        printf("%d ", i);
    }
    printf("\n");

    // 1から10までを3刻み
    printf("step 3: ");
    for (int i = 1; i <= 10; i += 3) {
        printf("%d ", i);
    }
    printf("\n");
    return 0;
}
実行結果
出力例:
step 2: 0 2 4 6 8
step 3: 1 4 7 10

配列をforで走査

配列の長さは sizeof(a) / sizeof(a[0]) で求めるのが定番です。

C言語
#include <stdio.h>

int main(void) {
    int a[] = {10, 20, 30, 40};
    size_t len = sizeof(a) / sizeof(a[0]);

    for (size_t i = 0; i < len; i++) {
        printf("a[%zu] = %d\n", i, a[i]);
    }
    return 0;
}
実行結果
出力例:
a[0] = 10
a[1] = 20
a[2] = 30
a[3] = 40

ネストしたfor文

2重ループで表や行列、九九などを作れます。

C言語
#include <stdio.h>

int main(void) {
    // 3x3の簡単な掛け算表
    for (int i = 1; i <= 3; i++) {
        for (int j = 1; j <= 3; j++) {
            printf("%2d ", i * j); // 幅2で整形
        }
        printf("\n");
    }
    return 0;
}
実行結果
出力例:
 1  2  3 
 2  4  6 
 3  6  9

制御構文と注意点

break/continueの使い方

breakはループ自体を脱出し、continueはその反復の残りをスキップして次の反復に進みます。

C言語
#include <stdio.h>

int main(void) {
    // continue: 奇数を飛ばして偶数だけ表示
    printf("continue: ");
    for (int i = 1; i <= 10; i++) {
        if (i % 2 != 0) {
            continue;          // 奇数はスキップ
        }
        printf("%d ", i);
    }
    printf("\n");

    // break: 7で打ち切る
    printf("break: ");
    for (int i = 1; i <= 10; i++) {
        if (i == 7) {
            break;             // 7になったらループ終了
        }
        printf("%d ", i);
    }
    printf("\n");
    return 0;
}
実行結果
出力例:
continue: 2 4 6 8 10
break: 1 2 3 4 5 6

無限ループ(for(;;))の書き方

for(;;)は条件を省略した無限ループです。

明示的にbreakするまで続きます。

C言語
#include <stdio.h>

int main(void) {
    int count = 0;

    // 実際には3回でbreakして終了
    for (;;) {                 // 無限ループの典型形
        count++;
        printf("tick %d\n", count);
        if (count == 3) {
            break;             // 条件が満たされたら抜ける
        }
    }
    return 0;
}
実行結果
出力例:
tick 1
tick 2
tick 3

オフバイワンエラーを防ぐ条件

配列の添字は0から始まるため、典型的な安全条件は < 長さ です。

<= と書くと1回余計に回って範囲外アクセスになる危険があります。

C言語
/* 誤り例: a[3] にアクセスしてしまう(未定義動作の危険)
int a[3] = {1,2,3};
for (int i = 0; i <= 3; i++) {   // <= 3 は1回多い
    printf("%d\n", a[i]);        // i == 3 で範囲外
}
*/
C言語
#include <stdio.h>

int main(void) {
    int a[3] = {1, 2, 3};

    // 正しい: i は 0,1,2 の3回
    for (int i = 0; i < 3; i++) {
        printf("%d ", a[i]);
    }
    printf("\n");
    return 0;
}
実行結果
出力例:
1 2 3

よく使う範囲と条件の対応は次の通りです。

取りたい範囲初期化条件更新
0..n-1i = 0i < ni++
1..ni = 1i <= ni++
m..n(両端含む)i = mi <= ni++
m..n(上端を含まない)i = mi < ni++
降順 n-1..0i = n-1i >= 0i–
降順(size_t)i = ni– > 0(更新部に i–)

for(…); の空文に注意

forの直後にセミコロンがあると、ループ本体が空文になってしまいます。

ブロックが別物として1回だけ実行されるため、意図と違う結果になります。

C言語
#include <stdio.h>

int main(void) {
    int count = 0;

    for (int i = 0; i < 3; i++); // ← ここでループが終わってしまう(空文)
    {
        count++;                 // これは1回だけ実行される
    }
    printf("count = %d\n", count);

    // 正しい書き方
    count = 0;
    for (int i = 0; i < 3; i++) {
        count++;
    }
    printf("count = %d\n", count);

    return 0;
}
実行結果
出力例:
count = 1
count = 3

for文とwhile文の違いと使い分け

構文の違いと読みやすさ

forは「初期化・条件・更新」を1行にまとめ、反復の全体像を明確にします。

whileは「条件だけ」を書くため、初期化や更新の場所が離れる分、柔軟ですが読み手が追跡しにくくなることがあります。

両者はしばしば等価に書けます。

C言語
#include <stdio.h>

int main(void) {
    // for版
    printf("for:   ");
    for (int i = 0; i < 5; i++) {
        printf("%d ", i);
    }
    printf("\n");

    // while版(上のfor文と等価)
    printf("while: ");
    int j = 0;      // 初期化
    while (j < 5) { // 条件
        printf("%d ", j);
        j++; // 更新
    }
    printf("\n");
    return 0;
}
実行結果
出力例:
for:   0 1 2 3 4
while: 0 1 2 3 4

for文を選ぶ場面/whileを選ぶ場面

回数がはっきりしている、または「開始値から終了値まで規則的に進む」処理ならforが自然です。

配列走査、カウンタ制御、表の生成などが該当します。

初期化・条件・更新がまとまり、ヒューマンエラー(更新忘れ、条件の抜け)を減らせます。

一方で、入力が枯渇するまで読み続ける、条件が複雑で更新の位置もケースによって変わる、リスナーがイベントを待ち続けるといった「回数が未確定なループ」はwhileの方が意図に合います。

また、for(;;)で無限ループを書くことも可能ですが、無限ループを扱う設計上の文脈ではwhile(1)と書かれることもあります。

プロジェクトのスタイルガイドに従い、意図が最も伝わる形を選ぶのが良いでしょう。

観点forwhile
初期化・条件・更新1行に集約分散しがち
読みやすさ反復の全体像が明確自由度が高いが追跡が必要
典型用途配列走査、固定回数、範囲ループ入力待ち、条件が変動、未確定回数
無限ループfor(;;)while(1)

まとめ

for文は、反復の初期化・条件・更新をひとまとめにして意図を明確にできる、C言語の基本かつ強力な構文です。

0からn-1の標準形、降順、ステップ幅、配列走査、ネストなどの基本パターンを押さえ、break/continueの挙動やfor(;;)の無限ループの扱いも理解しておくと、安全で読みやすいコードを書けます。

特にオフバイワンエラーはi < nを徹底することで多くを防げます。

while文との違いも踏まえ、回数が明確なときはfor、未確定なときはwhileと使い分ける習慣を身につけてください。

この記事を書いた人
エーテリア編集部
エーテリア編集部

プログラミングの基礎をしっかり学びたい方向けに、C言語の基本文法から解説しています。ポインタやメモリ管理も少しずつ理解できるよう工夫しています。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!