How to explain this operator associativity?

254 views Asked by At

According to this table, ++ has right to left associativity. So, I run this code:

int a = 5;
++a + ++a * ++a

and expect the expression to be 50 (as 8 + 7 * 6, increment starts from right to left). But the expression is evaluated from left to right (6 + 7 * 8) by Eclipse, and gives result as 62. I am new to this associativity in Java, and must be missing something obvious. Please help me understand this strange behavior.

EDIT: Thank you for your answers, but I have one more question now. It is that, as seen from @bizclop's code and tree answer, it is obvious that the associativity for ++ doesn't matter. Then, is there any use case for this associativity of ++/--?

2

There are 2 answers

2
biziclop On BEST ANSWER

There are two different things mixed up here: expression parsing and expression evaluation.

Let's start with the expression: ++a + ++a * ++a. What do we first have to do with it? Since operators + and * need two operands and ++ needs one, we have to figure out which operand goes with which operation. This is the expression parsing step, where precedence/associativity are applied.

  1. ++ has the highest precedence, so we can rewrite our expression as (++a) + (++a) * (++a)
  2. Next up it's *, so again we can add parentheses: (++a) + ((++a) * (++a))
  3. And lastly we have +, the lowest precedence of all, so for the sake of symmetry we can write: ((++a) + ((++a) * (++a)))

Note that we can represent this neatly as a tree:

   +
  / \
++   *
 |   | \
 a  ++ ++
     |  |
     a  a

So this is our evaluation tree based on precedence and associativity.

Note that in this case associativity didn't matter at all as all the operators had different precedence. Had our expression been 4 - 1 - 3 + 2, it would've been important to use associativity to reach (((4 - 1) - 3) + 2), as + and - have the same precedence.

Now comes the next step, evaluation. Evaluation always happens from left to right (even for assignments, though the rules are a bit quirky), but it happens left-to-right using the tree we've just built.

  1. So first of all we start evaluating the + operator, as it's on the top.
  2. We then go one level down to the left, as we evaluate the ++a on the left side of the + operator, (6)
  3. then we go to the right and start evaluating the * operation.
  4. The way we do it is to evaluate the second ++a, (7)
  5. then the third ++a (8)
  6. and then we multiply the result of steps 4 and 5 (this is the * operation evaluated), (56)
  7. and finally we add the result of step 6 to the result of step 2 (62)

...and we're done.

TL;DR: Precedence and associativity determine where to put parentheses but evaluation is always left-to-right.

15.7. Evaluation Order

The Java programming language guarantees that the operands of operators appear to be evaluated in a specific evaluation order, namely, from left to right.

1
Crazyjavahacking On

It is because multiplication operator * has higher precedence over the addition + operator.

The computation will be ++a + (++a * ++a) = 6 + 7 * 8