22

In this code:

int y = 10;
int z = (++y * (y++ + 5)); 

What I expected

First y++ + 5 will be executed because of the precedence of the innermost parentheses. So value of y will be 11 and the value of this expression will be 15. Then ++y * () will be executed. So 12 * 15 = 180. So z=180

What I got

z=176

This means that the VM is going from left to right not following operator precedence. So is my understanding of operator precedence wrong?

EdmDroid
  • 1,350
  • 1
  • 11
  • 25
  • 31
    Precedence does NOT mean the order things are executed. – user253751 Mar 20 '15 at 08:48
  • I'm always wondering why people even try to use this construct. If it's hard to figure out what happens (and needs a question on SO), then it's probably not suitable for production. I wouldn't be too happy if people on my team gave me this code at least. Just my two cents, and not an actual answer and/or question. – Caramiriel Mar 20 '15 at 10:12
  • 11
    @Caramiriel I'm 99% sure this is not production code - this is just prodding and poking at the language & compiler, and the OP feels that they have found something unexpected. – Richiban Mar 20 '15 at 11:13
  • Euhm I dont program in Java at all and even I knew the result should have been 11*16. Isn't this like basic math or something? – Loko Mar 20 '15 at 13:00
  • 6
    @Loko Basic math doesn't have constructs like `y++`, since basic math doesn't have mutable variables (as far as I know). – Kritzefitz Mar 20 '15 at 13:47
  • @Kritzefitz okay a very tiny bit programming knowledge and some math knowledge – Loko Mar 20 '15 at 13:48
  • Considering how much creators of Java tried to improve safety from C/C++, it's seems silly they didn't prohibit this. Compiler giving error straight away would have been a lot more productive, than countless people trying to figure out how the expression works. – user694733 Mar 20 '15 at 14:15
  • 3
    Your understanding of operator precedence is wrong; this is a very common misunderstanding and many beginner books explain this completely wrong. These articles are about C# but the principles apply equally well to Java; they might help you. http://ericlippert.com/tag/precedence/ – Eric Lippert Mar 20 '15 at 15:20
  • 15
    The key thing to understand is that precedence determines the order in which the *operators* are executed, not the order in which the *operands* are executed. `A() + B() * C()` guarantees that the multiplication operation happens before the addition. **The invocation of `A()` is neither a multiplication nor an addition**, so precedence says *nothing whatsoever* about whether `A()` happens before `B()` and `C()`. – Eric Lippert Mar 20 '15 at 15:23
  • 2
    Moreover: don't forget about *associativity*. In `A() + B() - C() * D()` is the multiplication done *before* or *after* the addition? It is done *after*. The multiplication comes before the subtraction because of precedence, the addition comes before the subtraction because of associativity. So we have `(A() + B()) - (C() * D())`. We compute the left side of the subtraction *before* the right side, and therefore the addition must happen *before* the multiplication. – Eric Lippert Mar 20 '15 at 16:03
  • In-lining a `++` should be a syntax error. Then we wouldn't have all this confusion over it. – jpmc26 Mar 20 '15 at 20:44

5 Answers5

24

The expression (++y * (y++ + 5)); will be placed in a stack something like this:

1. [++y]
2. [operation: *]
3. [y++ + 5] // grouped because of the parenthesis

And it will be executed in that order, as result

1. 10+1 = [11] // y incremented 
2. [operation: *]
3. 11+5 = [16] // y will only increment after this operation

The the expression is evaluated as

11 * 16 = 176
Uyghur Lives Matter
  • 18,820
  • 42
  • 108
  • 144
owenrb
  • 535
  • 2
  • 7
  • 11
    If you are working on a stack, the [operation: \*] should come *after* the two inputs. It doesn't affect the important bits of what you're saying here, so it's just a minor quibble. – Tim S. Mar 20 '15 at 12:12
  • 6
    I find this answer quite confusing. If you're considering a stack machine, the operations are: compute the side effect and value of ++y and push the result on the stack, then compute the side effect and value of y++ and put the result on the stack, then push 5 on the stack, then pop two things off the stack, add them, and push the sum on the stack, then pop two things off the stack, multiply them, and put the product on the stack. – Eric Lippert Mar 20 '15 at 17:54
  • Okay, using post-fix notation it is expressed as `[++y][y++][5]+*` or `11 11 5 + *`. During he first phase parsing it will push the 3 values into the stack `[5][11][11]` in that order. Next it will find the `+` operator and it will pop 2 values from the stack `11` and `5`, the result of the operation, which is `16`, will be pushed back into the stack, hence the stack state will be `[16][11]`. The next token is another operator `*`, so it will pop 2 values from the stack again and perform the operation: `11 * 16` (note: the 2nd value popped will be the first operand). – owenrb Mar 20 '15 at 18:57
  • @OwenBringino Realistically a high level programming language will not use a "stack", it will implement the rules of the grammar. So your analogy falls apart easily. –  Mar 20 '15 at 22:59
14

First y++ + 5 will be executed because of the precedence of the innermost parentheses

Precedence and evaluation order are not the same thing. All binary expressions except the assignment expression are evaluated left-to-right. Therefore y++ is evaluated before the parenthesized expression on the right.

Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
  • But then I don't understand the point of using parentheses in mathematical expressions – EdmDroid Mar 20 '15 at 08:39
  • 5
    @EdmDroid Without any parenthesis, `++y * y++ + 5` would be evaluated just as `(++y * y++) + 5` - that's a very different expression. – nos Mar 20 '15 at 08:46
  • 1
    I guess the choice of the term "precedence" causes confusion. It's actually *binding priority*, regulating how a chain of binary operations parses syntactically, and not a temporal precedence. – Marko Topolnik Mar 20 '15 at 08:59
  • While OP is confused, so is the answer: "All binary expressions except the assignment expression are evaluated left-to-right" is not correct or at least confusing: the multiplication is performed _after_ the addition although the latter is to the right of the multiplication. What is true that among pairs of *non-overlapping* formulas, the leftmost one is evaluated before the rightmost one; concretely this applies to `++y` on the left and `y++` or its containing `y++ + 5` on the right. On the other hand the formulas with `*` respectively `+` as operator overlap (latter is operand of former). – Marc van Leeuwen Mar 20 '15 at 13:51
  • 2
    The latter is not to the right of multiplication, it is the right *side* of the binary multiplication expression. The rule is very simple: evaluate the left operand, then evaluate the right operand, then evaluate the binary expression itself. No overlaps need to be considered, the expressions are strictly nested into a tree structure. – Marko Topolnik Mar 20 '15 at 16:04
12

The parentheses just describe how the sub-expressions will be grouped together. Parenthesizing doesn't mean it will be evaluated first. Rather, the rule in java is evaluate each sub-expression strictly from left to right.

Always remember that the order of evaluation has absolutely nothing to do with operator precedence and associativity.

Java Oracle documentation says that:

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.

Therefore, the expression (++y * (y++ + 5)) will be evaluated as

temp1 = ++y = 11
temp2 = y++ + 5 = 11 + 5 = 16 
z = temp1*temp2 = 11*16 = 176  

Further reading: Eric Lippert's blog, Precedence vs Associativity vs Order, explained in detailed about precedence, associativity and order of evaluation. Though this blog addresses but equally valid for too.

Community
  • 1
  • 1
haccks
  • 104,019
  • 25
  • 176
  • 264
4
  1. First will be executed ++y. y will be 11.
  2. Then will be executed y + 5 (actually y++ + 5 can be written as 5 + y++ which is interpreted as (5 + y) and then y++). z will become 11 * 16 = 176.
  3. y will be 12 after the calculation finishes.
Konstantin Yovkov
  • 62,134
  • 8
  • 100
  • 147
  • 2
    postfix ++ has higer precedence than binary +. It just happens that the value of the expression y++ is the value of y before the increment, but y is incremented as a side effect. – Brainstorm Mar 20 '15 at 08:40
  • Why `5 + y++` will be interpreted as `(5 + y)++` ? – haccks Mar 20 '15 at 14:51
  • I meant `(5 + y)` and then `y++` – Konstantin Yovkov Mar 20 '15 at 14:51
  • Still wrong. It is not necessary that side effect to `y` will take place after `y + 5`. – haccks Mar 20 '15 at 14:53
  • 2
    Indeed, this answer is misleading. Though in this case you cannot tell whether the increment side effect happens before or after the addition, you can come up with an example where you *can* tell the difference. Java does not allow the side effect of the increment to be delayed until after the addition. (Imagine a world for instance where addition could throw an exception on overflow; the side effect of the increment must be observed *before* the exception is possibly thrown, because a catch could observe the incremented variable.) – Eric Lippert Mar 20 '15 at 17:59
1

The calculation is going on following order

 z= (++10 * (10++ + 5))
 z= (11 * (11 + 5))//++ (prefix or postfix) has higher precedence than + or *
 z= (11 * 16)
 z= 176 
Masudul
  • 21,823
  • 5
  • 43
  • 58