Reputation:
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.
Upvotes: 1
Views: 191
Reputation: 263267
It returns 2
.
The "usual arithmetic conversions" are applied to the operands of the ==
operator. _Bool
is an unsigned type with a conversion rank lower than that of int
or unsigned 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 _Bool
to int
and yielding the value 1
. Now both operands are of the same type, so no further conversion is needed. So i == b
is equivalent to 42 == 1
, which is false.
In (_Bool)i == b
, the "integer promotions" are still applied to both operands, so both are converted from _Bool
to int
. (The conversion from int
to _Bool
and back to int
loses information, converting all non-zero values to 1
.) Now both operands are of the same type, so no further conversion is needed. So (_Bool)i == b
is equivalent to 1 == 1
, which is true -- and the function returns 2
.
(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 == 42u
promotes b
from _Bool
to int
, resulting in an int
vs. unsigned int
comparison. Since the operands have different signedness but the same conversion rank, the signed operand is converted to the unsigned type. Converting 1
from int
to unsigned int
is trivial, yielding 1u
. So the comparison is equivalent to 1u == 42u
, which is false.
(Note that the ==
operator in C, like the other equality and relational operators, yields a result of type int
with the value 0
or 1
, not a result of type _Bool
.)
Upvotes: 2
Reputation: 385
If both of the operands have arithmetic type, the usual arithmetic conversions are performed.
As such, in evaluating the expression i == b
, arithmetic conversion will occur. During arithmetic conversion, all involved operands are converted to the lowest ranked type that all can "fit" in, in this case int
.
Since 1 != 42
, the first condition is not true.
The second expression first casts i
to a _Bool
, resulting in true
. Then it evaluates true == true
which is obviously true
. Thus the function returns 2
.
Upvotes: 0
Reputation: 2915
Why not just run it?
It is actually return 2
. gcc version 4.5.4 with -std=gnu99
Upvotes: 0