Home > Enterprise >  Assigning a variable during arithmetic in Java?
Assigning a variable during arithmetic in Java?

Time:10-12

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.

CodePudding user response:

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.

CodePudding user response:

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.

CodePudding user response:

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.

  • Related