Operator precedence and evaluation order [duplicate]
Asked Answered
N

5

7

I can't understand output of this program:

#include<iostream>
using namespace std;
int main()
{
    int x = 1 , y = 1, z = 1;
    cout << ( ++x || ++y && ++z ) << endl; //outputs 1;
    cout << x << " " << y << " " << z ;  //x = 2 , y = 1 , z = 1;
    return 0;
}

Output:

1
2 1 1

If || is evaluated first then this output is fine, however this article says that && has a higher precedence than ||, and thus it must be evaluated first. If this is the case then according to me output should be:

1
1 2 2

as ++y && ++z would evaluate to true and thus ++x won't be evaluated.

Nelidanelie answered 24/8, 2016 at 14:29 Comment(2)
Precedence != evaluation order.Amarillo
There's a great article by Eric Lippert that explains the difference between precedence, associativity, and order of evaluation. It focuses more on C#, but it also deals with C++. Just one thing: he says in C++ the order of evaluation is free (unlike C#, where it's strictly left to right). Well, there are exceptions: the boolean operators AND and OR require left-to-right, so that short-circuiting can be applied, as in this case.Thaliathalidomide
M
7

"Precedence" affects grouping, not order, and means that if there could be any ambiguity regarding which operator an operand "belongs to", the operator with the higher precedence gets first dibs on it.

Since there are two binary operators involved, there are two ways you can read the expression.
As trees, these would be:

    and
    /\
   or ++z       [(++x || ++y) && ++z]
  / \
++x ++y 


   or
   /\
++x  and       [++x || (++y && ++z)]
     / \
  ++y ++z

The precedence rules determine that the latter tree is chosen in C++, since the middle operand, ++y, is grouped with &&, not with ||.

The "short-circuiting" of these operators means that evaluation must start at the leftmost leaf (each operator must first evaluate its left leg, then its right if it needs to).
Thus, ++x is evaluated first, and || only continues with its right leg if ++x is zero, which it isn't.

(As can be seen from the wonderful and artistic diagrams, ++x must be evaluated first regardless of the relative precedence of && and ||.)

Metastasize answered 24/8, 2016 at 15:23 Comment(0)
C
9

Let's put the excess parantheses in:

( ++x || (++y && ++z ))

Then it's easy to see that (++y && ++z ) will only be evaluated if ++x is 0. So you can see that irrespective of operator precedence, the short-circutting nature of || means that the right hand side is only evaluated if the left hand side is 0.

(If the right hand side is evaluted, then note that ++z will only be evaluated if ++y is not 0.)

Chorography answered 24/8, 2016 at 14:31 Comment(0)
K
9

&& has a higher precedence than ||, and thus it must be evaluated first.

No. Operator precedence only determines that how the operators will be bound tighter (as if by parentheses) to its arguments when parsing an expression, it doesn't influence evaluation order. In this case, it just means ++x || ++y && ++z will be parsed as (++x) || (++y && ++z), rather than (++x || ++y) && (++z).

Note that the associativity of operator|| is left-to-right, so ++x will be evaluated at first, and (++y && ++z) won't be evaluated because of short-circuit evaluation (other than overloaded operator||).

Kafka answered 24/8, 2016 at 14:33 Comment(0)
M
7

"Precedence" affects grouping, not order, and means that if there could be any ambiguity regarding which operator an operand "belongs to", the operator with the higher precedence gets first dibs on it.

Since there are two binary operators involved, there are two ways you can read the expression.
As trees, these would be:

    and
    /\
   or ++z       [(++x || ++y) && ++z]
  / \
++x ++y 


   or
   /\
++x  and       [++x || (++y && ++z)]
     / \
  ++y ++z

The precedence rules determine that the latter tree is chosen in C++, since the middle operand, ++y, is grouped with &&, not with ||.

The "short-circuiting" of these operators means that evaluation must start at the leftmost leaf (each operator must first evaluate its left leg, then its right if it needs to).
Thus, ++x is evaluated first, and || only continues with its right leg if ++x is zero, which it isn't.

(As can be seen from the wonderful and artistic diagrams, ++x must be evaluated first regardless of the relative precedence of && and ||.)

Metastasize answered 24/8, 2016 at 15:23 Comment(0)
O
1

This expression

 ++x || ++y && ++z

is equivalent to expression

++x || ( ++y && ++z )

and not like this

 ( ++x || ++y ) && ++z

If the first operand of the logical OR expression is evaluated to true (as in your example) then the second operand that is ( ++y && ++z ) is not evaluated.

Ovenbird answered 24/8, 2016 at 14:32 Comment(0)
S
0

( ++x || (++y && ++z )) - can be seen as boolean values - only ++x is evaluated. Its int value is 2 and the boolean value is 1 (true).

Slotter answered 24/8, 2016 at 15:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.