クイズ
突然ですが問題です。以下のプログラムをx86_64アーキテクチャ(64bit)上で動かした場合の実行結果はどうなるでしょうか?
#include <stdio.h> int main(int argc, char *argv[]) { unsigned long code = -1UL; printf("code = %016lx\n", code); printf("code >> 16 = %016lx\n", code >> 16); printf("code >> 63 = %016lx\n", code >> 63); printf("code >> 64 = %016lx\n", code >> 64); printf("code >> 65 = %016lx\n", code >> 65); return 0; }
回答は以下の通り。
(反転させて見てください)
[kaigai@masu ~]$ ./a.out code = ffffffffffffffff code >> 16 = 0000ffffffffffff code >> 63 = 0000000000000001 code >> 64 = ffffffffffffffff code >> 65 = 7fffffffffffffff
こりゃ驚いた。別に x86_64 に限った話ではなく、i386でも同様に、シフト演算子を使う時のシフト幅は sizeof(変数) * 8 でモジュロ演算した結果に落とされてしまう。
これを知らなかったせいで、x86_64では以下のコードが無限ループに落ちてしまった。うーむ、深い。
unsigned long maps[]; u64 bitmap; while (bitmap) { maps[index++] |= bitmap & (-1UL); bitmap = bitmap >> BITS_PER_LONG; }
ちなみにどうやって解決したか。
while (bitmap) { maps[index++] |= bitmap & (-1UL); bitmap = ((bitmap >> BITS_PER_LONG/2) >> BITS_PER_LONG/2); }
これでいいのだ。