見出し画像

C : sizeof returns unsigned

見つけにくいバグ

以下のCodeを見てください。
さて、なんと表示されるでしょうか?
答えは、"100"ではなく、"0"になります。

#include <stdio.h>
#include <stdlib.h>
int array[] = {12, 23, 45, 67, 89};
#define TOTAL_ELEMENTS sizeof(array)/sizeof(array[0])

int main() {
    int d = -1;
    int x = 0;
    if(d <= TOTAL_ELEMENTS){
        x = 100;
    }
     printf("%d\n", x);
     return 0;
}

マクロ定義、TOTAL_ELEMENTSは、unsigned intになります。なぜなら、sizeof演算子の結果は、unsignedなので。
if分の中身は、signedとunsignedの比較になり、unsignedに格上げされてから比較がなされます。すると、"-1"は、最大の正の値になるので、条件式は、偽となるのです。

このバグは、

#define TOTAL_ELEMENTS (int)(sizeof(array)/sizeof(array[0]))

とすることで修正できます。

Editor's note

不必要にunsigned型を使って、無用の複雑さを持ち込まないようにしましょう。「表現する値が、負になることはない」と言う理由だけで、unsignedを使わないこと。intのような、符号付きの型を使えば、複数の型を混在させた時の「格上げ」の規則に煩わされずに済みます。に済みます。
unsigned型を使うのは、ビットフィールドやバイナリマスクだけに限っても良い。

また、式にキャストをかけて、全オペランドを符号付き or 符号なし に統一すれば、コンパイラは結果の型を作り出さずに済みます。

もしよろしければ、サポートをお願いします! 頂いたサポートは、Creatorとしての活動費に充てさせて頂きます。