We have:
unsigned x = 1;
signed char y = -1;
this expression:
x > y
is used as the controlling expression of the if statement.
After usual arithmetic conversions the right operand y
will be converted to an unsigned int
value. The result of the conversion of the negative signed char
value -1
will be a huge unsigned int
value (equal to UINT_MAX
).
So the expression x > y
will be evaluated as:
1U > UINT_MAX
which is always false (i.e., evaluated to 0).
This is the short version. To explain how do we come to this result with the C standard rules, I explain it below.
Here is how it goes:
The >
relational operator is used, here it was C says on the relational operators:
Relational operators (C99, 6.5.8p3) "If both of the operands have arithmetic type, the usual arithmetic conversions are performed."
Ok, in our example both operand are of integer types and integer types are of arithmetic types. So usual arithmetic conversion will be done. What are the usual arithmetic conversions?
Usual arithmetic conversions (C99, 6.3.1.8p1) "Otherwise, the integer promotions are performed on both operands. Then the following rules are applied to the promoted operands:`
Ok, first integer promotions is done on each operand. How are the integer promotions performed?
Integer promotions (C99, 6.3.1.1p2) "if an int can represent all values of the original type, the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions."
y
is of signed char
type so it is first promoted to int
after integer promotions and x
is of unsigned int
type and stays an unsigned int
.
Then usual arithmetic conversions will find a common type between both operands. In our case, it means this:
Usual arithmetic conversions (suite) (C99, 6.3.1.8p1) "Otherwise, both operands are converted to the unsigned integer type corresponding to the type of the operand with signed integer type."
unsigned int
has the same conversion rank as the int
type (remember signed char
was promoted to int
), so the promoted y
will be converted from int
(after promotion) to unsigned int
. For information, integer conversion ranks are defined in (C99, 6.3.1.1p1).
As you can notice, unsigned int
wins over int
in usual arithmetic conversions, another way of saying this is to say that unsigned
is sticky.
Now how is an int
value of -1
(the signed char
-1
after its promotion to int
) converted to an unsigned int
value?`. Here is what C says on integer conversion in this specific case:
Integer conversions (C99, 6.3.1.3p2) "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."
This paragraph is written so its meaning remains independent of the signed number representation. For two's complement representation, it means the int
value -1
is converted to (UINT_MAX + 1) - 1
, which is equal to UINT_MAX
. So in our specific case,
x > y
is equivalent to
1U > UINT_MAX
is equivalent to
0