#include <stdio.h>
int main(void)
{
printf("%d", sizeof(signed int) > -1);
return 0;
}
the result is 0 (FALSE). how can it be? Im using 64bit ubuntu linux so the result should be (4 > -1) => 1 => True.
#include <stdio.h>
int main(void)
{
printf("%d", sizeof(signed int) > -1);
return 0;
}
the result is 0 (FALSE). how can it be? Im using 64bit ubuntu linux so the result should be (4 > -1) => 1 => True.
Thing is the sizeof
operator returns an unsigned quantity (size_t
). So the comparison promotes -1
to unsigned, which makes it looks like a really big number.
You can try:
printf("%d", ((int)sizeof(signed int)) > -1);
sizeof(signed int)
has type size_t
, which is an unsigned type. When you make a comparison between a signed and an unsigned value [and the unsigned value's type is at least as large as the signed value's type], the signed value is converted to unsigned before the comparison. This conversion causes -1
to become the largest possible value of the unsigned type. In other words, it is as if you wrote
#include <limits.h>
/* ... */
printf("%d", sizeof(signed int) > SIZE_MAX);
You can make gcc warn when you make this mistake, but it's not on by default or even in -Wall
: you need -Wextra
or more specifically -Wsign-compare
. (This warning can produce a great many false positives, but I think it's useful to turn on for new code.)
There are many implicit conversions in C, and it's helpful specifically to understand what are called the "usual arithmetic conversions", which include what are called the integer promotions.1
The actual rules are a bit complex, but, simplified, all scalar types are automatically converted when an operator has operands of different types. The conversion first takes the operand of lower rank and converts it to the type of the higher rank. Then, if only one operand is signed it is converted to unsigned unless the operand with signed type was larger and could have represented all of the unsigned type's values. That's not the case with your example because size_t is almost always as large or larger than int.
Finally, on almost all machines, -1 has all the bits set, making it a very large number when taken as unsigned.
1. ISO/IEC 9899:1999 ("C99") 6.3 Conversions