1

I want to ask a question about the code below.

int a=1, b=3, c=1;

if((a||c--)&&(c&&b--)) printf("%d",b);
printf("%d %d %d",a,b,c);

Why does the code prints "21 2 1" rather than "1 2 0" ?

Thanks for your help.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Storian
  • 23
  • 3

3 Answers3

3

Since the or is evaluated to true immediately in (a||c--), the c-- is never evaluated. The compiler does this. If a statement is true right off the bat, it won't bother evaluating the rest. So, c is never decremented as the right side of the or is never evaluated.

Lucas Streanga
  • 469
  • 2
  • 7
1

You can imagine this if statement

if((a||c--)&&(c&&b--)) printf("%d",b);

the following way

if ( a )
{
    if ( c )
    {
        if ( b-- )
        {
            printf("%d",b);
        }
    }
}
else if ( c-- )
{
    if ( c )
    {
        if ( b-- )
        {
            printf("%d",b);
        }
    }
}

So if the expression in the first if statement

if ( a )

evaluates to the logical true then this if statement

else if ( c-- )

never gets the control.

From the C Standard (6.5.14 Logical OR operator)

4 Unlike the bitwise | operator, the || operator guarantees left-to-right evaluation; if the second operand is evaluated, there is a sequence point between the evaluations of the first and second operands. If the first operand compares unequal to 0, the second operand is not evaluated.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
1

Both || and && force left-to-right evaluation - the LHS is evaluated first and all side effects applied, then based on the result the RHS is evaluated.

Both operators short-circuit:

  • for a || b, if a is non-zero, then the result of the expression is 1 regardless of the value of b, so b is not evaluated;
  • for a && b, if a is zero, then the result of the expression is 0 regardless of the value of b, so b is not evaluated.

&& has higher precedence than ||, so a || b && c is parsed as a || (b && c).

Putting all that together, (a||c--)&&(c&&b--) is evaluated as follows:

  1. a || c-- is evaluated as follows:
    1. a is evaluated - its result is 1, so
    2. c-- is not evaluated; because of this c's value is not changed, and
    3. the result of the expression is 1
  2. c && b-- is evaluated as follows:
    1. c is evaluated - its result is 1, so
    2. b-- is evaluated - its result is 3; as a side effect b is decremented, and
    3. the result of the expression is 1
  3. both a || c-- and c && b-- evaluate to 1

The values of a and c are unchanged (1 and 1, respectively), while b has been decremented and its value is now 2.

John Bode
  • 119,563
  • 19
  • 122
  • 198