Roshan Mathews said:
According to the precedence rules && has a higher precedence than
|| and both are 'left to right' associative. So in an expression
like
++i || ++j && ++k
where i, j, k are 0, -1, 0 (before the expression is evaluated),
shouldn't the && part be evaluated before the || part?
No. This higher precendence means nothing more than that a || b && c is
equal to a || (b && c), not to (a || b) && c. It says nothing about the
order in which any of the operands are evaluated.
This is just as true of * and +, or of [] and ==. [] having higher
precedence than == means that x == y[z] does evaluate to x == (y[z]),
not to the (nonsensical) (x == y)[z]. It does not mean that y and z are
evaluated before x.
There is a special case, however, for the && and || operators, which
guarantees the opposite of your what you suppose. They are said to
short-circuit; that is, they are required to be evaluated left-to-right,
and when the value of the entire expression is known, that value is
returned and no other operands are even looked at.
This means that ++i || ++j && ++k is handled like this:
Evaluate ++i. If this is true (non-zero), the whole expression is true
(to be precise, it is 1); stop here.
Ok, we now know that i used to be -1, and ++i was 0 (and since both
|| and && also introduce a sequence point, so is i, now; this is not
important in this example, but can be in other circumstances; e.g.,
it means that --i && a
does not invoke undefined behaviour).
Evaluate ++j. If it is zero, the sub-expression ++j && ++k is zero,
and since ++i is also zero if we've got this far, so is the entire
expression; if so, stop here.
Now we know that ++i was 0 and ++j was non-zero.
Evaluate ++k. If it's false, the expression is false (0); if it's
true (non-zero), the expression is true (specifically 1).
Richard