Consider the code:
int foo(void)
{
_Bool b = 1; // is true
int i = 42; // mean true in conditions
if (i == b)
return 1;
else if ((_Bool)i == b)
return 2;
else
return 3;
}
What will this function return according to the C standard (C99 or C11)?
P.S. On GCC 4.7.2 with -std=c99 option the function returns 2.
It returns
2.The “usual arithmetic conversions” are applied to the operands of the
==operator._Boolis an unsigned type with a conversion rank lower than that ofintorunsigned int.The “usual arithmetic conversions” are specified in section 6.3.1.8 “Usual arithmetic conversions” of either the C99 or C11 standard (the links are to recent drafts).
In
i == b, since there are no floating-point operands, the “integer promotions” are applied to both operands, promoting the right operand from_Booltointand yielding the value1. Now both operands are of the same type, so no further conversion is needed. Soi == bis equivalent to42 == 1, which is false.In
(_Bool)i == b, the “integer promotions” are still applied to both operands, so both are converted from_Booltoint. (The conversion fromintto_Booland back tointloses information, converting all non-zero values to1.) Now both operands are of the same type, so no further conversion is needed. So(_Bool)i == bis equivalent to1 == 1, which is true — and the function returns2.(Note: Due to some carelessness on my part in reading the standard, this is about the third major edit of this answer. I think I’ve got it right this time.)
In answer to a question in the comments,
b == 42upromotesbfrom_Booltoint, resulting in anintvs.unsigned intcomparison. Since the operands have different signedness but the same conversion rank, the signed operand is converted to the unsigned type. Converting1frominttounsigned intis trivial, yielding1u. So the comparison is equivalent to1u == 42u, which is false.(Note that the
==operator in C, like the other equality and relational operators, yields a result of typeintwith the value0or1, not a result of type_Bool.)