1. 症状
下記のようにswitchブロックの内部で変数宣言をおこなうとコンパイルエラーとなる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#include <stdio.h> int main(void) { int i; for (i = 0 ; i < 100 ; i++) { switch (i%2) { case 0: char msg_even[] = "EVEN"; printf("%3d is %s\n", i, msg_even); break; case 1: char msg_odd[] = "ODD"; printf("%3d is %s\n", i, msg_odd); break; default: printf("%3d is UNKNOWN\n", i); break; } } return 0; } |
1.1. Cコンパイラー(cc)のエラー・メッセージ
1 2 3 4 5 6 7 8 |
$ cc main.c main.c: In function 'main': main.c:9:17: error: a label can only be part of a statement and a declaration is not a statement char msg_even[] = "EVEN"; ^~~~ main.c:13:17: error: a label can only be part of a statement and a declaration is not a statement char msg_odd[] = "ODD"; ^~~~ |
1.2. C++コンパイラー(g++)のときのエラー・メッセージ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
$ g++ main.cpp main.cpp: In function 'int main()': main.cpp:12:18: error: jump to case label [-fpermissive] case 1: ^ main.cpp:9:22: note: crosses initialization of 'char msg_even [5]' char msg_even[] = "EVEN"; ^~~~~~~~ main.cpp:16:13: error: jump to case label [-fpermissive] default: ^~~~~~~ main.cpp:13:22: note: crosses initialization of 'char msg_odd [4]' char msg_odd[] = "ODD"; ^~~~~~~ main.cpp:9:22: note: crosses initialization of 'char msg_even [5]' char msg_even[] = "EVEN"; ^~~~~~~~ |
2. 原因
- C言語の場合、switch文が『一つのブロック・スコープ』であるため、スコープの途中で変数宣言を行うことができない。
- C++の場合、case文を『jumpラベル』として扱うため、case文に飛ぶ(jumpする)前に全ての変数の初期化が終わっていなければならない。
3. 修正方法
変数定義をブロックに内包する。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
#include <stdio.h> int main(void) { int i; for (i = 0 ; i < 100 ; i++) { switch (i%2) { case 0: { char msg[] = "EVEN"; printf("%3d is %s\n", i, msg); } break; case 1: { char msg[] = "ODD"; printf("%3d is %s\n", i, msg); } break; default: printf("%3d is UNKNOWN\n", i); break; } } return 0; } |