コードの一部:
long rangeVar = 0;
rangeVar = atol(p_value);
if (rangeVar >= -2147483648 && rangeVar <= 2147483647)
コンパイル時に私は得ます:
警告:この10進定数はISO C90でのみ符号なしです
前もって感謝します
10進整数定数のタイプの規則は、ISO C標準の1990年版と1999年版の間で変更されました。
1990バージョンでは、接尾辞なしの10進整数定数の型は、その値を表すことができるint
、long int
、またはunsigned long int
の最初のものです。 (C90にはlong long
またはunsigned long long
タイプがありませんでした)。
1999および2011バージョンでは、そのタイプはint
、long int
、long long int
のいずれかです。符号なしの型になることはありません。
特定の定数のタイプ(2147483648
など)は、使用しているコンパイラーの整数タイプの範囲によって異なります。コンパイラのlong
型がたまたま32ビットの場合、2147483648
は、コンパイラがC90ルールを使用する場合はunsigned long
型、C11を使用する場合はlong long
型になります。ルール(long long
は、少なくとも64ビットであることが保証されています)。コンパイラはこれについて警告しています。
接尾辞を追加して定数のタイプを指定することができますが、単純な署名付きint
の接尾辞はありません。 U
はunsigned int
に、L
はlong
に、UL
はunsigned longなどに追加できます。
-2147483648
はnot整数定数であることを覚えておくことが重要です。むしろ2147483648
自体は整数定数であり、-2147483648
はその定数に単項マイナス演算子を適用する式です。 C90ルールでは、定数のタイプがunsigned long
の場合、これはnsigned単項マイナスであり、符号なし算術のルールでは値2147483648
が生成されます。 C99またはC11の規則では、2147483648
はタイプ(符号付き)long long
である可能性が高く、それを否定すると-2147483648
もタイプlong long
になります。
この問題を回避するために(-2147483647 - 1)
を使用するコードが表示されることがあります。 32ビットのint
が与えられた場合、2147483647
はint
タイプであり、式の結果は、オーバーフローなしで予期されるint
値を生成します。
もちろん、コンパイラの整数型のサイズが異なる場合、これはさらに複雑になる可能性があります。
はい、それはコンパイラーでうまく処理されないことの1つです。問題は、コンパイル中に、これが否定される2147483648であり、2147483648が整数の範囲外であることです。 -2147483648でなくても!
とにかく、警告を取り除くために、-2147483648LL
と書いて定数を64ビット数に変えることができます。
それはやりすぎです。したがって、定数にはINT_MIN
を使用することをお勧めします。ただし、<limits.h>
を含める必要があります。
はい、2147483648は有効な正の値ではありません。32ビットマシンでは2の補数の範囲外であるため、一部のコンパイラでは、処理しないと必要な値が得られない可能性があることを警告しているだけです。現代的な方法での否定。
Limits.hの実装のほとんどを見ると、(-2147483647 - 1)
を使用してこれを回避していることがわかると思います。