Precedence of && over || [duplicate]

The || operator short-circuits - if its first operand evaluates to true (nonzero), it doesn't evaluate its second operand.

This is also true for &&, it doesn't use its second operand if the first one is false. This is an optimization that's possible because any boolean value OR true is true, and similarly, any boolean value AND false is always false.


OK, so you're confusing precedence with evaluation order. Nothing is contradictional here at all:

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

is grouped as

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

since && has higher precedence. But then the LHS of the OR operation is true, so the whole RHS with its AND operation is discarded, it isn't evaluated.


To your note in the edit: yes, you're wrong: operator precedence is still not the same as order of evaluation. It's just grouping.


Firstly, as you said it yourself, && has higher precedence, which means that operand grouping should be

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

Why you are saying that "according to operator precedence" it should be (++i || ++j) && (++k) is not clear to me. That just contradicts what you said yourself.

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

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

So, operator precedence rules tell you that the grouping should be

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

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


You say:

which is possible only when ++i || ++j && ++k is evaluated like this:

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

But, according to operator precedence rule it should be evaluated as:

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

The first grouping is correct because the precedence of && is higher than the precedence of ||. Then the expression as a whole evaluates the LHS of the ||, with the side-effect of incrementing i, which evaluates to true. That means that the RHS of the || (the && expression) is not evaluated at all because it is not needed to determine the truth of the overall expression.

So, the compiler is correct; you misunderstood precedence in some way.


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

You don't understand precedence, it seems, or you don't understand the interaction of precedence with order of evaluation. The first grouping gives higher precedence to &&.

If you have a + b * c, where * has a higher precedence than +, then it is evaluated as a + (b * c), is it not? Change + to || and * to && and the expressions are isomorphic and the interpretation is similar.

The big difference between the arithmetic expression and the logical expression is that the operands of the logical expression have to be evaluated left-to-right but the operands of the arithmetic expression do not; the compiler could evaluate b * c before evaluating a (but must evaluate b * c before doing the addition). By contrast, in the logical expression (a || b && c), the compiler must evaluate a before evaluating b && c, and when a turns out to be true, it must not evaluate either b or c, let alone b && c.