next up previous contents
Next: 4.2 括弧の対応関係 Up: 4. 制御構造1 繰り返し(for文) Previous: 4. 制御構造1 繰り返し(for文)

4.1 for 文の書式

繰り返し(ループ)の書式を以下に示す。

        for ( 初期化 ; 継続条件 ; 増分処理 ){
                文
        }

先に説明した3つの要素を括弧の中に書くが、セミコロンで必ず区切らなければ ならない。

初期化

初期化はループに入る前に、一度だけ実行される。実行結果は判断されない。

継続条件

継続条件は、繰り返しの前に常に評価される(毎回、検査する)。 0である場合は偽と判断し、ループを終了する。それ以外の値の場合は、真と 判断し、ループを継続する。( if 文の条件と同じ。)

増分処理

増分処理は、2回目のループの実行前に(1回目の処理時は、初期化をし、増分 処理は行なわれない)、実行される。その評価は行なわれない。

従って、繰り返しは次のような順序で行なわれる。

1.
初期化
2.
継続条件の検査(偽ならば終了する。)
3.
文の実行
4.
増分処理
5.
2. へ

文の実行の最中に以降の繰り返しをそれまでの継続条件の如何にかかわりなく、 終わらせるためには、break 文を用いる。

例1
        for ( i=0; i<10; i=i+1 ){
                printf("おはよう\n");
        }

この例では、初期化は i=0 で、整数変数 i に 0 を代入し、i < 10 が真で ある内は printf を実行する。最後の i = i + 1 が実際に i の値を増やしている。

注意 i = i + 1 は、数学的には明らかにおかしいが、 c 言語では正しい式である。 なぜならば、= は等号ではなく、代入演算だからであり、まず、右辺の i + 1が実行されて、評価される。例えば、最初に i = 0 だったならば、 i + 1 は、1 と評価され、その結果が、改めて、i に代入される。 つまり、i + 1 の結果は、一旦別の場所に 保存されているから、こうしたことが可能になる。 (このことは、i + 1 を実行しても i の値は変わらないことからも分かる。)

例2
        for ( i=10; i>0; i=i-1 ){
                printf("Hello!\n");
        }

この例は、先の例と同じであるが、初めが i=10 で、1づつ減らしながら、 i=1 まで逆順に10回のループを回している。

例3
        int i,x;
        x=0;
        for ( i=2; i<=20; i=i+2 ){
                x = x + i;
        }

この例は、初期値は i=2 で、増分は 2 で、i が 20 になるまで、x に その値を足していっている。つまり、2の倍数を2から20まで全部足す計算を している。結果は、 10 * (2 + 20)/2 = 110 となる。

例4
        x = 2;    /* 初期化条件がループの外にある */
        for ( ; x < 1000 ; ){
                x = x * x;
        }

この例は、間違っているようであるが、実はなんの問題もなく実行できる。 先に説明したとおり、初期化と増分処理は何の評価もしない。つまり、for 文の 実行には何の関係もしない(勿論、セミコロンを省略することは出来ない。) 従って、何もしないという意味で、空欄であってもよい。この例の場合は、 x2 を計算して、x に代入することを繰り返しており、x < 1000 を満たす 間は実行をするようになっている。ただ、注意するのは、x < 1000 だったら 必ず2乗を実行するので、繰り返しを終わったときには、x の値は 1000 を越えている点である。

例5
 おそるべき例
        for (;;){
        }

これも文法的には正しい。実は、for 文は継続条件の欄も空白であってよい。 勿論、その場合、継続条件がないので、終了しない! こうしたループを無限ループという。(決してやってみないこと。) こうした無限ループを終わらせる方法は、後に勉強する。

例6
 おそるべき例
        for ( i=0; i<10; i=i+1 ){
                i=2;
        }

これは、何も恐ろしくないように見えるが、実はこれも無限ループになっている。 なぜならば、i=2; が常に実行されるので(実際は、2回目以降の増分処理で i=i+1が継続検査の前に実行されるので、継続検査の時には必ず i=3 となっている)、 i<10 の継続検査が常に真となり、永遠に偽になることはない。

このように、c 言語では、繰り返しの変数も変数なので、ループの中で自由に値を 変えることが出来るので、注意が必要である。

例7
 ループが実行されない場合
        i = 10;
        for ( ; i<10; i=i+1 ){
                printf("Hello!\n");
        }

この例の場合、初期化を行なっておらず、ループの前で、i = 10 を実行している ので、継続検査において偽となり、ループは1回も実行されない。

例8
 ループを抜ける反則技
        for ( i=1; i<10; i=i+1 ){
                if (i==5){
                        i=11;
                }
        }

これは、一種の反則技であるが、ループ変数も変数であることを利用して、 for 文の中の if 文で、i が5に等しくなったら、強制的に i を 11 に しているために、次の継続検査で偽となり、ループを抜けてしまう。

例 9
 正式なループの抜け方
        for ( i=1; i<10; i=i+1 ){
                if (i==5){
                        break;
                }
        }

これは、例8と同じで、i の値が5になったらループを抜けるための 正式なやり方である。break は、繰り返しを止めてしまえ、という命令である。



Noriyo Kanayama