limits.h 標準ライブラリー・ヘッダー・ファイルで定義される long 型整数の限界は、次の表で示すように、32 ビット・モードと 64 ビット・モードでは異なります。
表 2. 32 ビット・モードおよび 64 ビット・モードにおける長整数の定数限界
シンボリック定数 | モード | 値 | 16 進数 | 10 進数 |
---|---|---|---|---|
LONG_MIN (signed long の最小値) | 32 ビット | -(231) | 0x80000000L | -2,147,483,648 |
64 ビット | -(263) | 0x8000000000000000L | -9,223,372,036,854,775,808 | |
LONG_MAX (signed long の最大値) | 32 ビット | 231-1 | 0x7FFFFFFFL | +2,147,483,647 |
64 ビット | 263-1 | 0x7FFFFFFFFFFFFFFFL | +9,223,372,036,854,775,807 | |
ULONG_MAX (unsigned long の最大値) | 32 ビット | 232-1 | 0xFFFFFFFFUL | +4,294,967,295 |
64 ビット | 264-1 | 0xFFFFFFFFFFFFFFFFUL | +18,446,744,073,709,551,615 |
この違いにより、次のような現象が生じます。
他の変数に割り当てたり、関数に渡されるときに long 型値がオーバーフローする場合は、以下を行う必要があります。
C および C++ では、定数の型識別は明示的規則に従って行われますが、多くのプログラムでは、16 進定数またはサフィックスのない定数を「型のない」変数として使用し、2 の補数表示によって 32 ビット・システムで許容される限界を超える値を表します。このような大きな値は 64 ビット・モードでは 64 ビット long 型に拡張されることが多いため、たいていの場合次のような境界領域で、予期しない結果が生じることがあります。
境界での予期しない副次作用の例をいくつか、次の表に示します。
表 3. long 型に割り当てられる定数の、境界での予期しない結果
long に割り当てられる定数 | 同等の値 | 32 ビット・モード | 64 ビット・モード |
---|---|---|---|
-2,147,483,649 | INT_MIN-1 | +2,147,483,647 | -2,147,483,649 |
+2,147,483,648 | INT_MAX+1 | -2,147,483,648 | +2,147,483,648 |
+4,294,967,726 | UINT_MAX+1 | 0 | +4,294,967,296 |
0xFFFFFFFF | UINT_MAX | -1 | +4,294,967,295 |
0x100000000 | UINT_MAX+1 | 0 | +4,294,967,296 |
0xFFFFFFFFFFFFFFFF | ULONG_MAX | -1 | -1 |
サフィックスのない定数では、型があいまいになることがあります。その場合、sizeof 演算の結果を変数に割り当てる場合など、プログラムの他の部分に影響が出ることが考えられます。例えば、32 ビット・モードでは、コンパイラーが 4294967295 (UINT_MAX) のような数値を unsigned long として入力すると、sizeof は 4 バイトを戻します。64 ビット・モードでは、この同じ数値が signed long となり、sizeof は 8 バイトを戻します。定数を関数に直接渡すと、同様の問題が起こります。
このような問題を回避するには、サフィックス L (long 型定数の場合) または UL (unsigned long 型定数の場合) を使用して、プログラムの他の部分における割り当てや式の計算に影響を与えると思われる定数をすべて明示的に入力します。上記の例では、4294967295U のように数値にサフィックスを付けると、コンパイラーは、32 ビット・モードまたは 64 ビット・モードで、この定数を常に unsigned int と認識するようになります。
long 値を左にビット・シフトした場合、 32 ビット・モードと 64 ビット・モードでは結果が異なります。下記の表の例は、以下のコード・セグメントを使用して long 型定数でビット・シフトを実行した場合の結果を示したものです。
long l=valueL<<1;
初期値 | シンボリック定数 | ビット・シフト後の値 | |
---|---|---|---|
32 ビット・モード | 64 ビット・モード | ||
0x7FFFFFFFL | INT_MAX | 0xFFFFFFFE | 0x00000000FFFFFFFE |
0x80000000L | INT_MIN | 0x00000000 | 0x0000000100000000 |
0xFFFFFFFFL | UINT_MAX | 0xFFFFFFFE | 0x1FFFFFFFE |