goto文をほとんど使わないので、goto文の飛び先のラベルについて、気になることを試してみた。
/* ヘッダファイルのインクルード */ #include <stdio.h> /* 標準入出力 */ /* main関数 */ int main(void){ /* 変数の宣言 */ int i; /* ループ変数i */ int j; /* ループ変数j */ /* 二重ループ */ for (j = 0; j < 5; j++){ /* jが5ならこのループは終了. */ for (i = 0; i < 5; i++){ /* iが5ならこのループは終了. */ /* iとjの出力. */ printf("i = %d, ", i); /* iを出力, */ printf("j = %dn", j); /* jを出力. */ /* iが1なら二重ループから一気に抜けて, newへ飛ぶ. */ if (i == 1){ /* iが1の時. */ goto new; /* gotoでnewに飛ぶ. */ } /* iが2なら二重ループから一気に抜ける. */ if (i == 2){ /* iが2の時. */ goto end; /* gotoでendに飛ぶ. */ } } } /* ラベルの設置 */ new: /* newラベル */ printf("newn"); /* "new"と出力. */ end: /* endラベル */ printf("endn"); /* "end"と出力. */ /* プログラムの終了 */ return 0; /* 0を返して正常終了. */ }
newとendの2つのラベルを用意し、先にnewに飛ぶようにすると、newの下のendは実行されるのかどうか。
$ vi label.c $ gcc label.c -o label $ ./label i = 0, j = 0 i = 1, j = 0 new end $
newに続いてendも実行された。
ということは、switch-case文と同様に、上の処理で止めなければいけない場合が出てくる。
/* ヘッダファイルのインクルード */ #include <stdio.h> /* 標準入出力 */ /* main関数 */ int main(void){ /* 変数の宣言 */ int i; /* ループ変数i */ int j; /* ループ変数j */ /* 二重ループ */ for (j = 0; j < 5; j++){ /* jが5ならこのループは終了. */ for (i = 0; i < 5; i++){ /* iが5ならこのループは終了. */ /* iとjの出力. */ printf("i = %d, ", i); /* iを出力, */ printf("j = %dn", j); /* jを出力. */ /* iが1なら二重ループから一気に抜けて, newへ飛ぶ. */ if (i == 1){ /* iが1の時. */ goto new; /* gotoでnewに飛ぶ. */ } /* iが2なら二重ループから一気に抜ける. */ if (i == 2){ /* iが2の時. */ goto end; /* gotoでendに飛ぶ. */ } } } /* ラベルの設置 */ new: /* newラベル */ printf("newn"); /* "new"と出力. */ /* 抜ける. */ break; /* breakで抜ける. */ end: /* endラベル */ printf("endn"); /* "end"と出力. */ /* プログラムの終了 */ return 0; /* 0を返して正常終了. */ }
switch-case文と同様に、breakを入れてみる。
$ vi label.c $ gcc label.c -o label label.c: 関数 ‘main’ 内: label.c:37:3: エラー: ループまたは switch 文の外にある break 文です break; /* breakで抜ける. */ ^ $
しかし、コンパイルエラー。
どうも、breakはwhileなどの繰り返し処理やswitch-case文だけのようである。
となると、return文や、exit関数ぐらいしかないのだろうか。
$ vi label.c $ gcc label.c -o label $ ./label i = 0, j = 0 i = 1, j = 0 new $
まあ、こうなるけども。
Sample/c/label/label/src/label at master · bg1bgst333/Sample · GitHub