2005年12月 1日

こんなプログラムはいやだ: INT_MIN / -1

昨日とは別の知人から、INT_MIN / -1 を計算するとおもしろいことになると教えてもらいました。次の C のプログラムをコンパイルして実行するとどのような結果になるでしょうか。

#include <limits.h>
int
main ()
{
    volatile int a = -1;
    printf("%d\n", INT_MIN / a);
    return 0;
}
 

結果は、プラットフォーム依存ですが、 x86 の上では SIGFPE (Floating point exception) で落ちると思います。 例によって、volatile をつけているのはコンパイラの最適化を防ぐためです。-1 をいったん、変数 a に入れているのも、コンパイラがコンパイル時に計算を済ませてしまうのを防ぐためです。

GCC で x86 用のインラインアセンブラを使うなら次のように書けます。

int
main()
{
    __asm__(
        "movl    $-1, %ebx;"
        "movl    $-2147483648, %eax;"
        "cltd;"
        "idivl   %ebx");
    return 0;
}

Java ではこのような計算は 言語仕様で定義されており、 Integer.MIN_VALUE / -1 == Integer.MIN_VALUE となります。

まとめ

INT_MIN はいろいろと厄介な挙動を引き起こす元となります。たとえば abs(INT_MIN) の結果は不定です。本日手元に届いた Java Puzzlers にも Integer.MIN_VALUE が関係する話題は 5つほど載っているようです。この本は Javaの落とし穴をつつきまくるという内容で、かなりおもしろそうです。