C言語で64bit整数定数を扱う場合の注意
vO~O¾ê C ÌV@\ および 9502 – shift of long long broken などを読むと分かる話ですが、C言語で64bit整数定数を扱う場合にはサフィックスとして l, ll, ul, ull (大文字/小文字の区別なし、u,l はどちらが先でも良い) などをつけていないとおかしなことになります。
例えば、下記のようなプログラムは意図したとおりには動きません(x86_64環境の gcc でやっています)。
$ cat hage.c #include <stdio.h> int main (void) { unsigned long int a = 0, b = 0, c = 0; a = (1 << 63); b = (1 << 31); c = (1 << 15); printf("sizeof unsigend long int = %lu\n", sizeof(unsigned long int)); printf("0x%lx >> 62 => 0x%lx\n", a, (a >> 62)); printf("0x%lx >> 30 => 0x%lx\n", b, (b >> 30)); printf("0x%lx >> 14 => 0x%lx\n", c, (c >> 14)); return 0; }
コンパイルしてみると警告が表示されます。また、実行すると警告が表示された部分以外の結果もおかしいことがわかります。
$ gcc -o hage hage.c hage.c: In function 'main': hage.c:6: 警告: 左シフト回数 >= 型の幅となっています $ ./hage sizeof unsigend long int = 8 0x0 >> 62 => 0x0 0xffffffff80000000 >> 62 => 0x3fffffffe 0x8000 >> 14 => 0x2
正しくは、
$ cat hage5.c #include <stdio.h> int main (void) { unsigned long int a = 0, b = 0, c = 0; a = (1UL << 63); b = (1UL << 31); c = (1UL << 15); printf("sizeof unsigend long int = %lu\n", sizeof(unsigned long int)); printf("0x%lx >> 62 => 0x%lx\n", a, (a >> 62)); printf("0x%lx >> 30 => 0x%lx\n", b, (b >> 30)); printf("0x%lx >> 14 => 0x%lx\n", c, (c >> 14)); return 0; } $ gcc -o hage5 hage5.c $ ./hage5 sizeof unsigend long int = 8 0x8000000000000000 >> 62 => 0x2 0x80000000 >> 30 => 0x2 0x8000 >> 14 => 0x2