Irfy
Irfy

Reputation: 9607

Understanding 2^31 and -2^31 integer promotion

#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?

Upvotes: 6

Views: 419

Answers (1)

DevSolar
DevSolar

Reputation: 70391

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>. ;-)

Upvotes: 13

Related Questions