Priority && over ||

As I know, the logical operator && has a higher priority than || . When running the code:

 #include <stdio.h> int main() { int i = 1, j =1, k = 1; printf("%d\n",++i || ++j && ++k); printf("%d %d %d",i,j,k); return 0; } 

gives the result:

 1 2 1 1 

which is possible only when ++i || ++j && ++k ++i || ++j && ++k is evaluated as follows:

 (++i) || (++j && ++k) 

But, according to the operator’s priority rule, it should be evaluated as:

 (++i || ++j) && (++k) 

and therefore the conclusion should be:

 1 2 1 2 

What is going on with this?

NOTE. In my opinion, I believe that an operator with a higher priority is evaluated as follows (if it is left associative):
1. Rate his left expression
2. Then evaluate its correct expression (if necessary)
I'm wrong?

+6
source share
4 answers

You speak:

which is possible only when ++i || ++j && ++k ++i || ++j && ++k is evaluated as follows:

 (++i) || (++j && ++k) 

But, according to the operator’s priority rule, it should be evaluated as:

 (++i || ++j) && (++k) 

The first grouping is correct because the && priority is higher than the priority || . Then the expression generally evaluates LHS || , with the side effect of increment i , which evaluates to true. This means that the RHS expression || (expression && ) is not evaluated at all, because there is no need to determine the truth of the general expression.

So, the compiler is right; You misunderstood the priority.


Why is the first grouping correct? According to the first grouping || has a higher priority than && . What is wrong with me?

You do not understand the priority, it seems, or do not understand the interaction of priority with the evaluation order. The first grouping gives higher priority to && .

If you have a + b * c , where * has a higher priority than + , then it evaluates to a + (b * c) , right? Change + to || and * on && , and the expressions are isomorphic and the interpretation is similar.

The big difference between an arithmetic expression and a logical expression is that the operands of the logical expression must be evaluated from left to right, but the operands of the arithmetic expression do not; the compiler can evaluate b * c before evaluating a (but must evaluate b * c before performing the addition). In contrast, in a logical expression ( a || b && c ), the compiler must evaluate a before evaluating b && c , and when a turns out to be true, it should not evaluate either b or c , not to mention b && c .

+6
source

Operator || short-circuit - if its first operand evaluates to true (nonzero), it does not evaluate its second operand.

This is also true for && , it does not use its second operand if the first is false. This is an optimization that is possible because any logical value OR true is true, and likewise, any logical value AND false is always false.


OK, so you are confusing priority with rating order. There is nothing contradictory here:

 ++i || ++j && ++k 

grouped as

 (++i) || (++j && ++k) 

since && has a higher priority. But then the LHS of the OR operation is true, so all RHS with its AND operation is discarded, it is not evaluated.


To the editorial note: yes, you are mistaken: the priority of the operator does not yet coincide with the evaluation order. This is just a grouping.

+12
source

First, as you said, && has a higher priority, which means that the grouping of operands must be

  (++i) || (++j && ++k) 

Why are you saying that “according to the priority of the operator” it should be (++i || ++j) && (++k) not clear to me. It just contradicts what you said yourself.

Secondly, the priority of the operator has absolutely nothing to do with the order of evaluation. Operator priority dictates the grouping between operators and their operands (i.e., operator priority indicates which operand belongs to the operator).

Meanwhile, the evaluation order is a completely different story. It either remains undefined, or is determined by a completely different set of rules. In the case of operators || and && evaluation order is indeed defined as from left to right (with obligatory early completion when possible).

So, operator precedence rules tell you that grouping should be

  (++i) || ((++j) && (++k)) 

Now the rules of the evaluation order tell you that we first evaluate ++i , then (if necessary) evaluate ++j , then (if necessary) evaluate ++k , then evaluate && and finally, we evaluate || .

+8
source

Since you underestimate priority, try to clear it with a math example. Multiplication and division have a higher priority than addition and subtraction. This means that this expression:

 a + b * c - d / e 

You can write like this:

 a + (b * c) - (d / e) 

Since you correctly stated that && has a higher priority than || , this expression:

 i || j && k 

can be written as follows:

 i || (j && k) 

You can think of it as that “the operation with the highest priority is first put in brackets” if that helps.

(But priority is different from rating — if i true, then (j && k) will never be rated.)

+3
source

Source: https://habr.com/ru/post/948573/


All Articles