3

My professor gave us this java snippet during a lecture and I don't understand why it outputs 12.

int b = 9; 
b = b + (b = 3); 
System.out.println( "b = " + b );

My thinking is that since parentheses give operations precedence, b would be reassigned to 3 first. Then, it would go b = 3 + 3 = 6. Obviously, this isn't the case and b = 9 + 3 = 12 is actually executed. Why is the code executed left to right and not parentheses first?

Excuse my poor title, I'm not sure what to call this because I don't think you ever actually program this way.

3 Answers 3

4

The entire expression on the right hand side is evaluated before the value of b is then changed. Also, it is evaluated from left to right. So the value of b does change during the evaluation of the expression, but the first b has already been sampled as 9 before the second term sets b to 3. It doesn't matter that b is eventually being set to the result of the expression. The term (b = 3) has the value 3. So the assignment is just:

b = 9 + 3

And so the result you get is 12.

On the other hand, the statement:

b = (b = 3) + b;

simplifies to

b = 3 + 3

Resulting in 6. This occurs because, again, the expression is evaluated left to right. So the first term has a value of 3 and also sets b to 3 before the second term b is then evaluated, and so has a value of 3.

Sign up to request clarification or add additional context in comments.

4 Comments

But why is the right-hand side evaluated before the value of b is changed? Don't the parentheses mean that b=3 is executed first which should also change the value of the first b? If I also have a=3 and do b = b * (b + a), (b+a) is executed before b is multiplied with the other value.
Yes, you are right. I just clarified it all for you. It's the order of evaluation that makes the big difference here.
@S.King the parentheses do not change the precedence in this case. In case of a * (b + c), the parentheses ensure that it is not interpreted as (a * b) + c. However, in the case of a + (b = c), there is no alternative interpretation, as (a + b) = c wouldn’t work at all. The parentheses are required to make embedding an assignment in another expression syntactically valid in the first place, not to alter an operator precedence.
I certainly hope that your professor gave you this example purely to make it clear why one should never code this way. While the language specification gives you a clear and unambiguous answer, the fact that you have to puzzle so hard over what it does should be evidence enough that using side-effects like this in the middle of the expression is asking for trouble. I surely hope your professor was clear about why he was sharing this terrible example.
2

Precedence does not mean that it runs first. It merely lets you rewire operator precedence. Ordinarily something like 1 + 2 * 3 is resolved as:

  • A plus operation between A and B, where
  • A is the integer literal '1'
  • B is the expression 2 * 3.

Why? Because operator precedence rules state that * binds tighter than +. With parens you can override that; (1 + 2) * 3 is a multiply operation between A and B where B is a '3' literal and A is '1 + 2'. That's all it does. It doesn't change the order in which things are resolved.

Java first evaluates 'b' (it's 9), then it evaluates (b = 3) (which is 3, and as a side effect, makes b become 3), and thus that expression is 12, which is then assigned to b, so it's 12.

Why does it evaluate the left hand side of that + first? Because the spec says so: resolves left to right.

Try this for funsies:

int b = 9;
b = (b = 3) + b;
System.out.println(b);

now it prints 6 as expected.

Comments

0

Here is an explanation related to machine language.

CPUs usually do not know about variables and operator precedence. They have a few registers that they can use to operate on, and memory cells to store data that exceeds their register capacity. Memory cells are numbered, and when we write variable b, the compiler will translate that into some memory cell's number - an address. The value stored at that addess is the value of the variable b.

But remember variables are not being calculated on - all this happens in the registers. So to add two numbers they have to be loaded into the CPU registers first.

int b = 9;

So in the above instruction the memory cell representing b is loaded with the value 9.

b = b + (b=3)

In this instruction b would get copied into a register (probably the accumulator, usually called register A) to be added with (b=3). Now the value 3 is loaded into the memory cell while the register has not changed, and finally the value 3 is added to what is still in the register: the old value of b.

Hence the operation results in

b = 9 + 3

and you have the 12.

In reality the time when the registers get loaded may differ since the assignment may be a subrouting requiring to reuse the registers for other stuff. But then, to avoid side effects the registers have to be restored so the programming logic stays the same.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.