user1150105
user1150105

Reputation:

Comparing with boolean variable in C

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

Answers (3)

Keith Thompson
Keith Thompson

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

George Pîrlea
George Pîrlea

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

louxiu
louxiu

Reputation: 2915

Why not just run it?

It is actually return 2. gcc version 4.5.4 with -std=gnu99

Upvotes: 0

Related Questions