warning: enumeration value ‘x’ not handled in switch
警告:列挙値 ‘x’ がswitch文で処理されません。
[-Wswitch]
■int型ではcase漏れを警告してくれない
#include <stdio.h>
#define 桃太郎 1
#define 犬 2
#define 猿 3
#define 雉 4
char *鳴き声(int 隊員){
switch(隊員){
case 犬: return "ワンワン" ;
case 猿: return "ウキーッ" ;
case 雉: return "ケーン";
}
return "想定外のバグ";
}
int main(void){
printf("%s\n",鳴き声(犬));
printf("%s\n",鳴き声(猿));
printf("%s\n",鳴き声(雉));
printf("%s\n",鳴き声(桃太郎));
}
このコードの桃太郎ように
case を記述し忘れる場合があります。
switch(int型)等と記述すると
gcc/clangは
case の抜けを指摘してくれません。
■enum型はcase漏れを警告してくれる
#include <stdio.h>
typedef enum {
桃太郎=1,犬,猿,雉,
} 桃組隊;
char *鳴き声(桃組隊 隊員){
switch(隊員){
case 犬: return "ワンワン" ;
case 猿: return "ウキーッ" ;
case 雉: return "ケーン";
}
return "想定外のバグ";
}
int main(void){
printf("%s\n",鳴き声(犬));
printf("%s\n",鳴き声(猿));
printf("%s\n",鳴き声(雉));
printf("%s\n",鳴き声(桃太郎));
}
gcc/clangコンパイラは
switch(enum型)と記述すると
case の抜けを指摘してくれます。
enum型の全てのメンバーが
case 文に記述されているか、
default節が記述されているか、
確認してください。
参考:
https://www.jpcert.or.jp/sc-rules/c-msc01-c.html
■enumの最初の定数を非ゼロにするとデバッグが楽になる
#include <stdio.h>
typedef enum {
Sun=1,//最初の定数を非ゼロにするとデバッグが楽になる
Mon,
Tue,
Wed,
Thu,
Fri,
Sat
} week ;
char *num2Week(week w) {
switch(w){
case Sun: return "日曜日";
case Mon: return "月曜日";
case Tue: return "火曜日";
case Wed: return "水曜日";
case Thu: return "木曜日";
case Fri: return "金曜日";
case Sat: return "土曜日";
default:
return
"未初期化変数は、"
"たまたま0である事が多いので"
"enumの先頭を非ゼロにするとバグを見つけやすい" ;
}
}
int main(void){
printf("%s\n",num2Week(Sun));
week x ; //初期化忘れのバグ
printf("%s\n",num2Week(x));
}
上記のプログラムで
enumの先頭でSun=1の設定をしていないと、
初期化していない xを引数にしてnum2Week(x)を呼んだ場合
”日曜日”が表示され(る事が多く)
問題検出が困難となる。
参考:
https://www.gfd-dennou.org/arch/comptech/cstyle/cstyle-ja.htm
から引用
「15 デバッグ
enum では、最初の定数はノンゼロにするか、 あるいはエラーを示すものにする。
enum { STATE_ERR, STATE_START, STATE_NORMAL, STATE_END } state_t;
enum { VAL_NEW=1, VAL_NORMAL, VAL_DYING, VAL_DEAD } value_t;
こうすると、 初期化していない変数はしばしば自発的に「エラー」になってくれる。」