【C言語】
enumとswitchを活用して
プログラムをスマートに書こう

switch(enum)のすすめ

warning: enumeration value ‘x’ not handled in switch

警告:列挙値 ‘x’ がswitch文で処理されません。
[-Wswitch]

■#defineでは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節が記述されているか、
確認してください。


参考:

MSC01-C. 論理的な完全性を追求する

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;
こうすると、 初期化していない変数はしばしば自発的に「エラー」になってくれる。」