I’m learning to code in C and cant understand the short circuit behaviour of the logical expressions. Do they not follow the precedence order

79 views Asked by At

I’m learning to code in C. I was going through the logical expressions but then this question came and I couldn’t understand ? Like are logical operators exceptional in case of precedence. Let’s take this one example:

i = 1; j = 1; k = 1;
printf("%d ", ++i || ++j && ++k);
printf("%d %d %d", i, j, k);

The compiler answer is 1 ,2,1,1 which means it short circuited. But i can’t understand that why didn’t the compiler follow the precedence (++ has higher precedence than ||) or is it just the way it’s designed in case of logical expressions? I just want to confirm. Thanks.it shows operator precedence

3

There are 3 answers

0
autistic On

There are a number of sequence points, which are markers for which prior side-effects (such as assignment/increment) must be complete by, and two of those sequence points are && and ||. The ternary control?true:false operator also has sequence points in it, hence why the side-effects of the first operand are complete before the second or third operands are evaluated.

0
Code to Fail On

The short circuit behaviour of || in C is only evaluating the right hand side if the left side was evaluated false.

In your case:

    int i=1, j=1, k=1;
    printf("%d ", ++i || ++j && ++k);  // prints 1 and only increments i
    printf("%d %d %d", i, j, k);

As the right hand side is never evaluated the variables j and k are not incremented.

0
chqrlie On

You must distinguish precedence that determines the way expressions are parsed and evaluation rules which determine what parts of expressions are evaluated and, in some cases, in which order:

  • ++ indeed has higher precedence than || and so does && so the expression printf("%d ", ++i || ++j && ++k); is parsed as:

     printf("%d ", ((++i) || ((++j) && (++k))));
    
  • evaluation rules determine what parts of the expression get evaluated: to evaluate A || B, A is evaluated first and the result is tested for its truth value: if A is true, ie: if it is not false, then the expression value is 1 and B is not evaluated at all (this is called short cut evaluation). If A evaluates to a false value, then B is evaluated and the value of the whole expression is 0 if B evaluates to a false value and 1 otherwise.

    The same rule applies to A && B except B is evaluated if and only if A evaluates to a truth value.

As a consequence, the steps to evaluate printf("%d ", ++i || ++j && ++k); are:

  • ++i evaluates to the value of i + 1, and i is incremented as a side effect before the next sequence point. The value is 2.
  • || causes a sequence point, and since the left operand is non 0, its right operand ++j && ++k is not evaluated at all, so no side effects on j or k will happen. The value of the expression is 1 and i gets the value 2.
  • the argument value 1 is passed to printf
  • the argument value "%d " is passed to printf. Note that the order of evaluation of function arguments and function objects is unspecified.
  • printf is called, outputs 1 and returns 2, the number of bytes produced, which is ignored.
  • the next printf outputs 2 1 1 because i was incremented and neither j nor k were.