Why is this happening with the sizeof operator when comparing with a negative number? [duplicate]

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 )

Leave a Comment