C言語でプログラムを書くとき、同じ処理を何度も繰り返したい場面はとても多いです。
その代表がfor文による繰り返し処理です。
本記事では、for文の基本構文から、breakやcontinueの使い方、よくあるミスと注意点まで、図解とサンプルコードを交えながら丁寧に解説します。
while文との違いも整理しながら、初心者でも迷わず使えるようになることを目指します。
C言語のfor文とは
for文でできることとwhile文との違い
for文は、決まった回数分だけ処理を繰り返したり、一定の規則で値を変化させながら処理を行ったりするときに最もよく使われる構文です。
まず、for文とwhile文のイメージの違いを図で確認してみます。

for文では、次の3つが1行にまとまっています。
- 初期化(例:
int i = 0;) - 繰り返し条件(例:
i < 10) - 変化式(例:
i++)
これらがfor文のかっこ内に集約されているため、「何から始めて、どこまで、どう変化させるか」が一目でわかりやすい構造になっています。
対してwhile文では、初期化はループの前、変化式はループの中に書くことが多く、処理が分散してしまいます。
そのため、繰り返し回数が明確な場合にはfor文を使うほうが読みやすく安全です。
少し例を見てみます。
同じ処理(0〜4を表示)をfor文とwhile文で書いたものです。
for文で0〜4を表示する例
#include <stdio.h>
int main(void) {
// iを0から4まで変化させながら繰り返す
for (int i = 0; i < 5; i++) {
printf("%d\n", i);
}
return 0;
}
0
1
2
3
4
while文で0〜4を表示する例
#include <stdio.h>
int main(void) {
int i = 0; // 初期化はループの前
while (i < 5) { // 条件式
printf("%d\n", i); // 繰り返したい処理
i++; // 変化式はループの中
}
return 0;
}
0
1
2
3
4
どちらでも同じ動作をしますが、for文のほうが「iをどう扱っているか」がひと目でわかりやすいと感じるはずです。
for文の基本構文と書き方のルール
for文の基本構文は次のようになります。
for (初期化; 条件式; 変化式) {
// 繰り返したい処理(ループ本体)
}
かっこの中は;で3つに区切られていることが大きなポイントです。

具体的な例を示します。
#include <stdio.h>
int main(void) {
// 初期化: int i = 0;
// 条件式: i < 5
// 変化式: i++
for (int i = 0; i < 5; i++) {
printf("iの値は%dです。\n", i);
}
return 0;
}
iの値は0です。
iの値は1です。
iの値は2です。
iの値は3です。
iの値は4です。
for文を書くときの主なルール・注意点を整理します。
- セミコロン
;は必ず2つ必要です。1つでも抜けると文法エラーになります。 - 初期化・条件式・変化式はいずれも省略可能ですが、意味が変わるので後で詳しく説明します。
- 繰り返したい処理が1行だけの場合、
{ }を省略できますが、基本的には必ず書くことをおすすめします。将来行を追加したときのバグを防げます。
C言語for文の基本的な使い方
繰り返し回数を指定するfor文の書き方
for文の最も基本的な使い方は、「何回繰り返すか」を指定する方法です。

例として、ユーザに繰り返し回数を入力させ、その回数だけメッセージを表示するプログラムを見てみます。
#include <stdio.h>
int main(void) {
int n;
printf("繰り返す回数を入力してください: ");
scanf("%d", &n); // ユーザから回数を入力
// iを0からn-1まで変化させながら繰り返す
for (int i = 0; i < n; i++) {
printf("%d回目の処理です。\n", i + 1);
}
return 0;
}
繰り返す回数を入力してください: 3
1回目の処理です。
2回目の処理です。
3回目の処理です。
ここで重要なのは、条件式i < nが満たされている間だけ繰り返すという点です。
iは0から始まり、n-1までの値を取ることになります。
インクリメント(i++)とデクリメント(i–)の使い方
for文では、カウンタ変数を少しずつ変化させるためにi++やi--がよく使われます。
インクリメントは「1増やす」、デクリメントは「1減らす」という意味です。

インクリメント(i++)を使った例
#include <stdio.h>
int main(void) {
// 1から5までの数を表示する
for (int i = 1; i <= 5; i++) { // iを1ずつ増やす
printf("%d\n", i);
}
return 0;
}
1
2
3
4
5
i++はi = i + 1と同じ意味ですが、for文ではほぼ必ずi++のような短い書き方を使います。
デクリメント(i–)を使った例
逆方向にカウントダウンする例も見ておきます。
#include <stdio.h>
int main(void) {
// 5から1までの数を表示する
for (int i = 5; i >= 1; i--) { // iを1ずつ減らす
printf("%d\n", i);
}
return 0;
}
5
4
3
2
1
このように、増える方向のループか、減る方向のループかによって、初期値・条件式・変化式を揃えることが重要です。
初期化・条件式・変化式の省略と注意点
for文のかっこ内の3つの部分は、実はそれぞれ省略することができます。
ただし、省略すると意味が変わるため注意が必要です。

代表的なパターンを表で整理します。
| 書き方の例 | 省略している部分 | 意味・挙動 |
|---|---|---|
for (int i = 0; i < 10; i++) | なし | 通常のfor文 |
for (; i < 10; i++) | 初期化 | iはループの前で準備しておく |
for (int i = 0; ; i++) | 条件式 | 条件なし(常に真)なので無限ループ、ただし他の場所で抜ける |
for (int i = 0; i < 10; ) | 変化式 | iの増減をループ本体の中で行う |
for (;;) | すべて | 完全な無限ループ |
特に注意すべきなのは、条件式を省略すると「常に条件が真」とみなされるという点です。
意図せず無限ループにならないよう気を付けましょう。
初期化を省略する例
ループの前で変数を初期化し、ループ内の初期化を省略した例です。
#include <stdio.h>
int main(void) {
int i = 0; // ここで初期化
// for文のかっこ内では初期化を省略
for (; i < 3; i++) {
printf("i = %d\n", i);
}
return 0;
}
i = 0
i = 1
i = 2
このように、外側で初期化した変数を使い回したいときに、初期化部分を省略することがあります。
条件式を省略した例(無限ループ)
#include <stdio.h>
int main(void) {
int i = 0;
// 条件式を省略したため、無限ループになる
for (;; i++) {
printf("i = %d\n", i);
if (i >= 4) {
// iが4以上になったらループを抜ける
break;
}
}
return 0;
}
i = 0
i = 1
i = 2
i = 3
i = 4
条件式を省略した場合はかならずループの中で抜ける処理(例えばbreak)を書く必要があります。
変化式を省略した例
#include <stdio.h>
int main(void) {
// 変化式を省略し、本体の中でiを増やす
for (int i = 0; i < 5; ) {
printf("i = %d\n", i);
i++; // ここで増やさないと無限ループになる
}
return 0;
}
i = 0
i = 1
i = 2
i = 3
i = 4
変化式を省略した場合、iの増減を忘れると無限ループになるため、あまり多用しないほうが安全です。
for文で使うbreakとcontinue
breakでfor文のループを途中終了する方法
break文は、今実行しているループを途中で強制的に終了する命令です。
条件に合致したらそれ以降の繰り返しを行わず、for文の外へ抜けます。

例として、1〜10まで数えながら、最初に見つけた3の倍数でループを終了するプログラムです。
#include <stdio.h>
int main(void) {
for (int i = 1; i <= 10; i++) {
printf("%dをチェック中...\n", i);
if (i % 3 == 0) {
printf("%dは3の倍数なので、ループを終了します。\n", i);
break; // ここでfor文から抜ける
}
}
printf("for文の外に出ました。\n");
return 0;
}
1をチェック中...
2をチェック中...
3をチェック中...
3は3の倍数なので、ループを終了します。
for文の外に出ました。
breakはあくまで「現在のループ1段分」から抜けるだけであり、ネストしたループでは「内側のループだけ」を終了することに注意してください(ネストについては後ほど解説します)。
continueで処理をスキップして次の繰り返しに進む方法
continue文は、「今の1回分の残りの処理」をスキップして、次の繰り返しに進む命令です。
ループ自体は続きます。

例として、1〜10のうち、偶数だけを表示するプログラムを見てみます。
#include <stdio.h>
int main(void) {
for (int i = 1; i <= 10; i++) {
// iが奇数のときは残りの処理をスキップ
if (i % 2 == 1) {
continue; // 次のiへ
}
// ここに到達するのは偶数のときだけ
printf("%dは偶数です。\n", i);
}
return 0;
}
2は偶数です。
4は偶数です。
6は偶数です。
8は偶数です。
10は偶数です。
continueの後に書いたコードは、その回のループでは実行されません。
処理を読みやすくするために、continueを使いすぎないことも大切です。
breakとcontinueの違いと使い分け
breakとcontinueの動作の違いを、図と表で整理します。

表でも比較してみます。
| キーワード | ループへの影響 | その回の残りの処理 | 以降の繰り返し |
|---|---|---|---|
break | ループ自体を終了 | 実行されない | まったく行われない |
continue | ループは続行 | 実行されない | 次の繰り返しに進む |
使い分けの考え方としては、次のように整理するとよいです。
- ループ全体を終わらせたいとき →
break - 特定の条件のときだけ、その回の一部処理を飛ばしたいとき →
continue
C言語for文でよくある書き方と注意点
ネストしたfor文(入れ子ループ)の書き方
for文の中にさらにfor文を書くことを「ネスト(入れ子)」と呼びます。
2重、3重にネストすることで、2次元・3次元のデータを扱う処理が書けます。

例として、2重ループを使って九九の一部を表示してみます。
#include <stdio.h>
int main(void) {
// 外側のループ: 段(1〜3段だけ表示)
for (int dan = 1; dan <= 3; dan++) {
// 段の見出し
printf("%dの段:\n", dan);
// 内側のループ: 掛ける数(1〜9)
for (int i = 1; i <= 9; i++) {
printf("%d x %d = %d\n", dan, i, dan * i);
}
printf("\n"); // 段の区切りに空行を入れる
}
return 0;
}
1の段:
1 x 1 = 1
1 x 2 = 2
1 x 3 = 3
1 x 4 = 4
1 x 5 = 5
1 x 6 = 6
1 x 7 = 7
1 x 8 = 8
1 x 9 = 9
2の段:
2 x 1 = 2
2 x 2 = 4
2 x 3 = 6
2 x 4 = 8
2 x 5 = 10
2 x 6 = 12
2 x 7 = 14
2 x 8 = 16
2 x 9 = 18
3の段:
3 x 1 = 3
3 x 2 = 6
3 x 3 = 9
3 x 4 = 12
3 x 5 = 15
3 x 6 = 18
3 x 7 = 21
3 x 8 = 24
3 x 9 = 27
ネストしたfor文では、ループ変数の名前を変える(例: iとj, xとy)こと、インデント(字下げ)をきちんと行うことが、読みやすさとバグ防止の鍵になります。
無限ループを書く場合の注意点
場合によっては、「終了条件が決まっていない」処理のために、あえて無限ループを書くことがあります。
代表的な書き方は次の2つです。
for (;;)while (1)あるいはwhile (true)(C99以降、stdbool.h利用時)

for文での無限ループの例と、抜け方を示します。
#include <stdio.h>
int main(void) {
int count = 0;
// 無限ループ: forの3要素をすべて省略
for (;;) {
printf("ループ回数: %d\n", count);
count++;
// 10回実行したらループを抜ける
if (count >= 10) {
printf("10回実行したのでループを終了します。\n");
break; // 無限ループから抜ける
}
}
return 0;
}
ループ回数: 0
ループ回数: 1
ループ回数: 2
ループ回数: 3
ループ回数: 4
ループ回数: 5
ループ回数: 6
ループ回数: 7
ループ回数: 8
ループ回数: 9
10回実行したのでループを終了します。
無限ループを書くときの注意点は次の通りです。
- 必ずどこかに終了条件を書く(例:
if (...) break;) - 外部からの入力やエラー発生などのタイミングで抜けられるように設計する
- デバッグ中に抜けられなくなったときに備え、途中経過を表示するprintfを一時的に入れておくと原因調査に役立つ
オフバイワンエラーを防ぐfor文の書き方
オフバイワンエラー(off-by-one error)とは、「1回多い」「1回少ない」繰り返しミスのことです。
配列の添字やループ回数でとても起きやすいバグであり、for文でも頻出です。

配列とfor文の組み合わせでよくあるミスを例に見てみます。
間違った例(配列の要素数を超えてアクセス)
#include <stdio.h>
int main(void) {
int numbers[5] = {10, 20, 30, 40, 50};
// 間違ったループ: i <= 5 なので6回回ってしまう
for (int i = 0; i <= 5; i++) {
printf("%d\n", numbers[i]); // iが5のとき、範囲外を参照してしまう
}
return 0;
}
このコードは、配列numbersの有効な添字範囲が0〜4であるにも関わらず、iが5のときにアクセスしてしまい、未定義動作を引き起こします。
配列のインデックスは「0から要素数-1」であることを常に意識する必要があります。
正しい例(オフバイワンを防いだ書き方)
#include <stdio.h>
int main(void) {
int numbers[5] = {10, 20, 30, 40, 50};
// 正しいループ: i < 5 とする
for (int i = 0; i < 5; i++) {
printf("%d\n", numbers[i]); // iは0〜4の範囲
}
return 0;
}
10
20
30
40
50
オフバイワンエラーを防ぐためのポイントを整理します。
- 配列
a[N]を全部回すときは、必ずi = 0; i < N; i++と書く - 「以下」「以上」の
<=よりも、「より小さい」「より大きい」の<を使うと、安全な境界チェックになりやすい - 配列の要素数は定数やマクロで表現し、数字の書き間違いを防ぐ
定数を使った方が安全な例も示します。
#include <stdio.h>
#define SIZE 5 // 配列の要素数を定数で定義
int main(void) {
int numbers[SIZE] = {10, 20, 30, 40, 50};
// SIZEを使うことで、配列の大きさを変更してもループが自動的に追従する
for (int i = 0; i < SIZE; i++) {
printf("%d\n", numbers[i]);
}
return 0;
}
10
20
30
40
50
このように、配列の大きさとループ回数を「同じ定数」にしておくと、オフバイワンエラーをかなり防ぐことができます。
まとめ
for文は、C言語で最もよく使われる繰り返し構文の1つであり、「初期化」「条件式」「変化式」が1カ所にまとまっていることが大きな特徴です。
本記事では、基本構文から、インクリメント・デクリメント、省略記法、breakとcontinueの動作、ネストしたfor文、無限ループの注意点、オフバイワンエラーの防ぎ方までを詳しく解説しました。
実際に小さなプログラムを書きながら試していくことで、for文の挙動が自然と身につきます。
繰り返し処理を自在に扱えるようになると、C言語で書けるプログラムの幅が一気に広がりますので、ぜひ手を動かして練習してみてください。
