Les Cargill said:
Nope. -2147483648 is a perfectly valid ( although somewhat
ambiguous ) 32 bit value ( assuming long is 32 bits for
what you are doing ). It is 0x8000000. So is 2147483648.
0x80000000 is never ambiguous.
Not quite.
In C99 and later, a decimal constant's type is the first of:
int, long int, long long int
in which it fits. In C90 (before long long was invented), the
sequence takes a left turn into unsigned land:
int, long int, unsigned long int
-2147483648 is not a constant; it's a constant expression consisting
of a unary "-" applied to the contant 2147483648.
Assuming int and long are 32 bits and long long is 64 bits (if it
exists), in C90 the constant 2147483648 is of type unsigned long.
Applying unary "-" to it yields an unsigned long result with
the same value. Initializing the int object "a" with that value
causes it to be converted from unsigned long to (signed) int --
which, since 2147483648L is outside the range of int, yields an
implementation-defined value. That value is very likely to be
-2147483648, which is what was intended.
In C99 and later the constant 2147483648 is of type long long, since
it won't fit in a long. Applying unary "-" gives you an expression
of type long long with the value -2147483648. Converting that
value to int unambiguously yields the int value -2147483648.
So as of C99, the declaration
int a = -2147483648;
is unambiguous and initializes a to the obvious value; in C90, it
*probably* does so.
The rules for octal and hexadecimal constants are a bit different. In
C90, the sequence is:
int, unsigned int, long int, unsigned long int
and in C99 and later, its:
int, unsigned int, long int, unsigned long int, long long int,
unsigned long long int
So changing the declaration to:
int a = -0x80000000
doesn't help for C90 (though it may remove the warning); the constant
is of type unsigned int, and the conversion is implementation-defined
(but very likely to yield the result you want). And in C99 and
later, it actually introduces an ambiguity, since -0x80000000 is of
type unsigned int, whereas -2147483648 is of type (signed) long long.
The warning, I think, refers just to the constant 2147483648,
without regard to its context.
If you're willing to assume that int is 32 bits (more specifically,
that INT_MIN == -2147483648 (mathematically)), then you can just
write:
int a = INT_MIN;
If not, you can write:
int a = -2147483647-1;
to avoid the warning.
For the second declaration, you could write:
long long int b = 2147483647+1;
or
long long int b = 2147483648LL;
If you can't assume that int is at least 32 bits, things could
get a bit more complicated; there's no guarantee that the value
-2147483648 can be stored in an int.