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
.