1

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

Waris..
  • 11
  • 3
  • 1
    I think you're confusing operator precedence and *order of evaluation*. See [Short circuit and operator precedence in C](https://stackoverflow.com/questions/61750969/short-circuit-and-operator-precedence-in-c) – WhozCraig Oct 01 '22 at 11:12
  • The precedence doesn't strictly define the evaluation order. E.g. in `a + b == c * d`, the `==` must be evaluated after `+` and `*` because of the precedence, but `*` doesn't have to be evaluated before `+`. – HolyBlackCat Oct 01 '22 at 11:24

3 Answers3

0

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.

autistic
  • 1
  • 3
  • 35
  • 80
0

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

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.
chqrlie
  • 131,814
  • 10
  • 121
  • 189