【C言語】0を無理にマクロにするとかえってマジックナンバーになる

■間違った理解・正しい理解

●間違った理解
マジックナンバーとは裸の数字の事である。
マクロは裸の数字ではないので
マジックナンバーではない。
●正しい理解
マジックナンバーとは意味のわからない数字の事である。


■無理に0をマクロにした例

#define ZERO    0U 
#define ONE     1U  
#define TWO     2U  
#define THREE   3U
#define TOP_OF_ARY      0   //配列の先頭添字
#define MY_PROJECT_ZERO 0   //自プロジェクト用ゼロ
int f(void) {
    //自動変数の初期化
    int x = MY_PROJECT_ZERO ;
    int y = MY_PROJECT_ZERO ;
    int z = MY_PROJECT_ZERO ;

    char    ary[] = "string";
    for(char *p = &ary[TOP_OF_ARY]; *p != ZERO ; p += ONE){
        printf("%c\n",p[ZERO]);    
    }
    
    //長い処理
    return  x+y+z;
}

0は小学生でも知っている数字なので
べたで0と記述した方がわかりやすいです。
逆に、
余計なマクロを定義して変数初期化等で多用すると
コードが非常に読みにくくなります。
つまり
#define  MY_PROJECT_ZERO  0
int  x  =  MY_PROJECT_ZERO ;
より
int  x  =  0 ;
のほうが読みやすいです。


■0と書いたほうがわかりやすい例

int g(void) {
    //自動変数の初期化
    int x = 0 ;
    int y = 0 ;
    int z = 0 ;

    char    ary[] = "string";
    for(char *p = &ary[0]; *p != '\0'; p++){
        printf("%c\n",p[0]);    
    }
    
    //長い処理
    return  x+y+z;
}

こう書いてください


■マジックナンバー禁止と言われて

#define ICHI    1
#define NI      2
#define SAN     3
double  三角形の面積(double 底辺,double 高さ){
    return  (底辺 * 高さ)/ NI ;
}

マクロでNIと書くと
かえって何だかわからなくなるので、
べたでと書いてください


■文脈から自明な定数をマクロにする必要なし

#define _0x000000FF       0xFF
#define _0x0000FF00     0xFF00
#define _0x00FF0000   0xFF0000
#define _0xFF000000 0xFF000000
#define SHIFT_eight         8
#define SHIFT_sixteen       16
#define SHIFT_twenty_four   24
uint32_t swap32NG(uint32_t value) {
    uint32_t ret;
    ret  = (value & _0x000000FF) << SHIFT_twenty_four;
    ret |= (value & _0x0000FF00) << SHIFT_eight;
    ret |= (value & _0x00FF0000) >> SHIFT_eight;
    ret |= (value & _0xFF000000) >> SHIFT_twenty_four;
    return ret;
}

文脈から自明な定数を
無理にマクロにすると却ってわかりにくくなります。


■16進数で書いたほうがわかりやすい例

uint32_t swap32OK(uint32_t value) {
    uint32_t ret;
    ret  = (value & 0x000000FF) << 24;
    ret |= (value & 0x0000FF00) << 8;
    ret |= (value & 0x00FF0000) >> 8;
    ret |= (value & 0xFF000000) >> 24;
    return ret;
}

やかましい静的解析ツールはこのコードに対して
マジックナンバーを使ったと文句を言うかもしれません。

そういう時は静的解析ツールのサポートセンターに
どう書くべきか質問しましょう。

併せて下記参考の DCL06-EX1 の対処方法も
サポートセンターに質問すると良いでしょう。


参考:

DCL06-EX1: 数値定数をシンボル定数に置き換えることは多くの場合よいプラクティスであるが、やりすぎになる場合もある。

https://www.jpcert.or.jp/sc-rules/c-dcl06-c.html

■クイズ

11
unsigned char型の最大値マクロはUCHAR_MAXですが最小値マクロは何?