问题
Piece of code :
long rangeVar = 0;
rangeVar = atol(p_value);
if (rangeVar >= -2147483648 && rangeVar <= 2147483647)
On compiling I get:
warning: this decimal constant is unsigned only in ISO C90
Thanks in Advance
回答1:
The rules for the types of decimal integer constants changed between the 1990 and 1999 editions of the ISO C standard.
In the 1990 version, an unsuffixed decimal integer constant's type is the first of int
, long int
, or unsigned long int
in which its value can be represented. (C90 had no long long
or unsigned long long
type).
In the 1999 and 2011 versions, its type is one of int
, long int
, long long int
; it's never of any unsigned type.
The type of a particular constant (such as 2147483648
) will vary depending on the ranges of the integer types for the compiler you're using. If your compiler's long
type happens to be 32 bits, then 2147483648
will be of type unsigned long
if your compiler uses C90 rules, or of type long long
if it uses C11 rules (long long
is guaranteed to be at least 64 bits). The compiler is warning you about this.
You can add suffixes to specify the type of a constant -- but there's no suffix for plain signed int
. You can add U
for unsigned int
, L
for long
, UL
for unsigned long, and so forth.
It's important to keep in mind that -2147483648
is not an integer constant; rather 2147483648
by itself is an integer constant, and -2147483648
is an expression that applies a unary minus operator to that constant. Under C90 rules, if the constant is of type unsigned long
, that's an unsigned unary minus, which under the rules of unsigned arithmetic yields the value 2147483648
. Under C99 or C11 rules, 2147483648
is likely to be of type (signed) long long
, and negating it yields -2147483648
, also of type long long
.
You'll sometimes see code that uses (-2147483647 - 1)
to avoid this problem; given a 32-bit int
, 2147483647
is of type int
and the result of the expression yields the expected int
value without overflow.
Of course if your compiler has different sizes for the integer types, this can become even more complicated.
回答2:
Yes, that's one thing that isn't handled very well by the compiler. The problem is that during compilation, this is the number 2147483648 which is negated, and 2147483648 is out of range for an integer. Even if -2147483648 wouldn't be!
Anyway, to get rid of the warning, you can turn the constant into a 64 bit number by writing -2147483648LL
.
That's overkill though, so the preferred way would be to use INT_MIN
for the constant. But then you'll need to include <limits.h>
.
回答3:
Yes, 2147483648 is not a valid positive value because it is out of range for 2's complement on 32 bit machines, so they are just trying to warn you that on some compilers this may not give you the value you want if they don't handle the negation in a modern way.
I feel it's worth adding another answer to point out that if you look at most limits.h implementations, you'll see that they get around this using (-2147483647 - 1)
.
来源:https://stackoverflow.com/questions/9941261/warning-this-decimal-constant-is-unsigned-only-in-iso-c90