オーバーフローの様を観測してみる

百聞は一見に如かずシリーズ第二弾
前回int型の変数の値をビット列で表示してみて、負の数が実際に2の補数になっていることを確かめました。
今回はint型の変数がオーバーフローする様を眺めてみましょう

/* 整数をオーバーフローさせてみる */
#include <stdio.h>

main()
{
    int x;
    void displayBits(int);
    displayBits(2147483647);
    printf("2147483647 + 1を計算してみる\n");
    displayBits(2147483647+1);
    printf("\n");
    displayBits(-2147483648);
    printf("-2147483648 - 1を計算してみる\n");
    displayBits(-2147483648-1);
    return 0;
}

void displayBits(int value)
{
    size_t sz = sizeof(int);
    int c, displayMask = 1 << sz * 8 - 1;

    printf("%+d = ", value);

    for (c = 0; c < sz * 8; c++) {
        putchar(value & displayMask ? '1' : '0');
        value <<= 1;

        if (c % 8 == 7)
            putchar(' ');
    }

    putchar('\n');
}

これを実際に(コンパイル時にwarningが出るけど><)実行してみると

+2147483647 = 01111111 11111111 11111111 11111111 
2147483647 + 1を計算してみる
-2147483648 = 10000000 00000000 00000000 00000000 

-2147483648 = 10000000 00000000 00000000 00000000 
-2147483648 - 1を計算してみる
+2147483647 = 01111111 11111111 11111111 11111111 

2進数としてみると1足したり、1引いたりしているだけなんだけど、先頭の符号を表すビットが反転してしまうために、コンピュータの解釈が真逆になってしまうのですね。*1
百聞は一見に如かず

*1:正確には1引くのではなく、1の2の補数表現(1が32ビット連なったもの)を足しているわけですが