This question already has an answer here:
-
sizeof() operator in if-statement
5 answers
What\'s really happening here? The output now is \"False\":
#include <stdio.h>
int main()
{
if (sizeof(int) > any_negative_integer)
printf(\"True\");
else
printf(\"False\");
return 0;
}
If I change it to:
if (sizeof(int) < any_negative_integer)
the output is \"True\".
Update: the same question has already been asked, I could not find it before asking.
sizeof returns size_t
which is unsigned and so -1
is being converted to a very large unsigned number. Using the right warning level would have helped here, clang
with the -Wconversion
or -Weverything
(note this is not for production use) flags warns us:
warning: implicit conversion changes signedness: \'int\' to \'unsigned long\' [-Wsign-conversion]
if (sizeof(int) > -1)
~ ^~
For gcc
you receive a similar warning using the -Wextra
flag:
warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
if (sizeof(int) > -1)
^
For reference, we know size_t is unsigned from the draft C99 standard section 7.17
Common definitions which says:
size_t
which is the unsigned integer type of the result of the sizeof operator;[...]
Note, it does not specify anything else about the type, in my specific case it happens to be unsigned long but it does not have to be.
The conversion of -1
is due to the usual arithmetic conversion covered in section 6.3.1.8
Usual arithmetic conversions which says:
[...]
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.
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.
Otherwise, both operands are converted to the unsigned integer type
corresponding to the type of the operand with signed integer type.
So the only time -1
would not be converted to an unsigned value would be if int could represent all the values of size_t, which is not the case here.
Why -1
ends up being a large unsigned value, actually it ends up being being the max value of the unsigned type is due to section 6.3.1.3
Signed and unsigned integers which says:
Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or
subtracting one more than the maximum value that can be represented in the new type
until the value is in the range of the new type.49)
So we end up with:
-1 + (UMAX + 1)
which is:
UMAX
and thus end up with:
if (sizeof(int) > UMAX )
Because sizeof()
returns a size_t
, an unsigned type. Comparing signed and unsigned types can give surprising results due to implicit casting before the comparison.