Conversion rules are more complicated when unsigned operands are involved. The problem is that comparisons between signed and unsigned values are machine-dependent, because they depend on the sizes of the various integer types. For example, suppose that int is 16 bits and long is 32 bits. Then -1L < 1U, because 1U, which is an unsigned int, is promoted to a signed long. But -1L > 1UL because -1L is promoted to unsigned long and thus appears to be a large positive number.
I tried the code below in two different scenarios:
- compiled on an x86 64bits platform and executed. Where
sizeof(-1L)
-> 8byte andsizeof(1U)
-> 4 bytes - compiled on an x86 32bits platform and executed. Where
sizeof(-1L)
-> 4byte andsizeof(1U)
-> 4 bytes
The code:
int main() {
if(-1L > 1U)
printf("true");
else
printf("false");
return 0;
}
The results:
- x86 64bits:
false
- x86 32bits:
true
lets explain the rank system first
6.3.1 Arithmetic operand(c99 standard)
A) The rank of a signed integer type shall be greater than the rank of any signed integer
type with less precision(more bytes higher precision higher rank)
B) The rank of long long int shall be greater than the rank of long int, which shall be
greater than the rank of int, which shall be greater than the rank of short int, which
shall be greater than the rank of signed char.
C) The rank of any unsigned integer type shall equal the rank of the corresponding signed
integer type, if any.
(in other words if your system unsigned int is 32bits and your int is 32bits then the
ranks of these are the same.)
the above explains the rank.
now coming to arithmetic conversions.
6.3.1.8 Usual arithmetic conversions (c99 standard)
1)If both operands have the same type, then no further conversion is needed.
2)Otherwise, if both operands have signed integer types or both have unsigned integer
types, the operand with the type of lesser integer conversion rank is converted to the
type of the operand with greater rank.(similar to 1)
3)Otherwise, if the operand that has unsigned integer type has rank greater or equal to
the rank of the type of the other operand, then the operand with signed integer type is
converted to the type of the operand with unsigned integer type.
4)Otherwise, if the type of the operand with signed integer type can represent all of the
values of the type of the operand with unsigned integer type, then the operand with
unsigned integer type is converted to the type of the operand with signed integer type
5)Otherwise, both operands are converted to the unsigned integer type corresponding to the
type of the operand with signed integer type.
2) compiled on an x86 32bits platform and executed. Where sizeof(-1L) -> 4byte and sizeof(1U) -> 4 bytes
in your case look at statement 3 & C. the unsigned value(4bytes) has rank equal to the signed value(4btyes) therefore the singed value is converted to an unsigned value, when this happens the, the sign bit makes this look like a extremely large value. -1L > 1U therefore is true
1) compiled on an x86 64bits platform and executed. Where sizeof(-1L) -> 8byte and sizeof(1U) -> 4 bytes
in this case, the unsigned value rank is less than the rank of the singed value. look at 4). the signed integer(8bytes) can represent any 4byte unsigned value. therefore the unsigned 4byte value is converted to a signed value.(this will preserve the sign bit, sign bit is 0)
therefore -1L > 1U is false