#include <stdio.h>
int main() {
printf("sizeof(int): %zu\n", sizeof(int));
printf("%d\n", 2147483648u > -2147483648);
printf("%d\n", ((unsigned int)2147483648u) > ((int)-2147483648));
printf("%d\n", 2147483648u != -2147483648);
printf("%d\n", ((unsigned int)2147483648u) != ((int)-2147483648));
return 0;
}
The output of this code in both C and C++, on cygwin64 and an rhel6.4 machine with gcc 5.2.0 is:
sizeof(int): 4
1
0
1
0
According to "Integer promotions", 2147483648u
will be of type unsigned int
(even without the u
suffix) and -2147483648
of type int
(as usual). Why the different results with explicit casting?
According to the "Usual arithmetic conversions", this paragraph applies:
Otherwise, the signedness is different: If the operand with the unsigned type has conversion rank greater or equal than the rank of the type of the signed operand, then the operand with the signed type is implicitly converted to the unsigned type
This means that the correct result is as if:
2147483648u > 2147483648u
2147483648u != 2147483648u
were performed, because in 32 bits, signed -2^31 and unsigned 2^31 have the same representation. In other words, the result with casting is correct. What is going on?
I have the feeling that somehow, a higher-rank integer promotion is applied without casting, so I'm getting e.g. a 64-bit signed promotion on both sides -- but why?
Both executables are compiled as 64-bit, can this play a role?
There are no negative integer constants. There are only positive ones with the unary -
operator applied.
Since 2147483648 > INT_MAX
, that promotes 2147483648
to the next larger signed (because you did not append u
) integer type, before the -
is applied.
By the way, that is why INT_MIN
is usually defined as (-INT_MAX - 1)
in <limits.h>
. ;-)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With