I got this over email from Sanjay Bhupathiraju. He is correct that the explanation is wrong in the book. And the correct explanation is great so I'm including it here and linking from the errata.
On Page 59, in the following expression, the steps shown to evaluate the expression are misleading and breaks the right interpretation. But the end result seem to correct although the steps shown in your book are incorrect.
Question to evaluate the following expression.
int x = 3;
int y = ++x * 5 / x-- + --x;
Here is the step by step approach for solving this problem.
1. All Post-unary Operators should be evaluated first as per Table 2.1 in your book. The evaluation should have been done for post increment operant first. So the evaluation really should be the following in the next step.
y = ++x * 5 / 3 + --x; // After the evaluation, the value of x is 2.
2. Now, all Pre-unary operators should be evaluated in the expression from left to right.
y = 3 * 5/3 + 2;
3. Now the multiplication/division/modulus operators should be applied from left to right.
y = 15/3 + 2;
y = 5 + 2;
Answer: y = 7;
Although the answer for this expression y is 7 in the approach shown in your book, it is really misleading for the reader to not evaluate the post increment or the post decrement operand first on the original expression.
And Sanjay: it's not misleading in the book - it's wrong! Whereas your explanation is correct. We were lucky that the answer happened to come out the same. But the reason the book is misleading is different. (Roel explains below)
According to me (and my little program) the eplanation in the book is correct! In Java, subexpressions are evaluated from left to right (when there is a choice). So, for example in the expression A() + B() * C(D(), E()), the subexpressions are evaluated in the order A(), B(), D(), E(), and C(). C() is evaluated last, because it requires the results from D() and E().Output:
++x 4 | x-- 4 | --x 2 |
Let's look at another example:If the post-unary operator is always executed first, both statements should print exactly the same values for both i and j. But the output is different (for j):
4-80 And it makes sense, because subexpressions are evaluated from left to right, so you'll have
And probably the most obvious example. Let's use a short-circuit operator:If the post-unary operator is always executed first, this program should print 11-true, but it doesn't: it prints 10-true because the left operand (i3 < 15) is evaluated first and evaluates to true. And because || is a short-circuit operator, the right operand (i3++ > 10) is not evaluated (and thus i3 is not incremented).