web-dev-qa-db-ja.com

警告:この10進定数は、ISO C90でのみ符号なしです

コードの一部:

long rangeVar = 0;
rangeVar = atol(p_value);

if (rangeVar >= -2147483648 && rangeVar <= 2147483647)

コンパイル時に私は得ます:

警告:この10進定数はISO C90でのみ符号なしです

前もって感謝します

20
user1227514

10進整数定数のタイプの規則は、ISO C標準の1990年版と1999年版の間で変更されました。

1990バージョンでは、接尾辞なしの10進整数定数の型は、その値を表すことができるintlong int、またはunsigned long intの最初のものです。 (C90にはlong longまたはunsigned long longタイプがありませんでした)。

1999および2011バージョンでは、そのタイプはintlong intlong long intのいずれかです。符号なしの型になることはありません。

特定の定数のタイプ(2147483648など)は、使用しているコンパイラーの整数タイプの範囲によって異なります。コンパイラのlong型がたまたま32ビットの場合、2147483648は、コンパイラがC90ルールを使用する場合はunsigned long型、C11を使用する場合はlong long型になります。ルール(long longは、少なくとも64ビットであることが保証されています)。コンパイラはこれについて警告しています。

接尾辞を追加して定数のタイプを指定することができますが、単純な署名付きintの接尾辞はありません。 Uunsigned intに、Llongに、ULはunsigned longなどに追加できます。

-2147483648not整数定数であることを覚えておくことが重要です。むしろ2147483648自体は整数定数であり、-2147483648はその定数に単項マイナス演算子を適用する式です。 C90ルールでは、定数のタイプがunsigned longの場合、これはnsigned単項マイナスであり、符号なし算術のルールでは値2147483648が生成されます。 C99またはC11の規則では、2147483648はタイプ(符号付き)long longである可能性が高く、それを否定すると-2147483648もタイプlong longになります。

この問題を回避するために(-2147483647 - 1)を使用するコードが表示されることがあります。 32ビットのintが与えられた場合、2147483647intタイプであり、式の結果は、オーバーフローなしで予期されるint値を生成します。

もちろん、コンパイラの整数型のサイズが異なる場合、これはさらに複雑になる可能性があります。

13
Keith Thompson

はい、それはコンパイラーでうまく処理されないことの1つです。問題は、コンパイル中に、これが否定される2147483648であり、2147483648が整数の範囲外であることです。 -2147483648でなくても!

とにかく、警告を取り除くために、-2147483648LLと書いて定数を64ビット数に変えることができます。
それはやりすぎです。したがって、定数にはINT_MINを使用することをお勧めします。ただし、<limits.h>を含める必要があります。

10
Mr Lister

はい、2147483648は有効な正の値ではありません。32ビットマシンでは2の補数の範囲外であるため、一部のコンパイラでは、処理しないと必要な値が得られない可能性があることを警告しているだけです。現代的な方法での否定。

Limits.hの実装のほとんどを見ると、(-2147483647 - 1)を使用してこれを回避していることがわかると思います。

1
Peter M