Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple assignment on one line not working as expected

Tags:

I'm trying to swap two ints - x and y in the example, and do it in one line without a library function.

So I started with this:

int x = 4;
int y = 3;

System.out.println(x);
System.out.println(y);

x ^= y;

System.out.println(x);
System.out.println(y);

y ^= x;

System.out.println(x);
System.out.println(y);

x ^= y;

System.out.println(x);
System.out.println(y);

The output was 4, 3, 7, 3, 7, 4, 3, 4 as expected. All good so far.

Next up was this:

int x = 4;
int y = 3;

System.out.println(x);
System.out.println(y);

y ^= (x ^= y);

System.out.println(x);
System.out.println(y);

x ^= y;

System.out.println(x);
System.out.println(y);

The output was 4, 3, 7, 4, 3, 4 as expected once again. Still good so far.

Then finally this:

int x = 4;
int y = 3;

System.out.println(x);
System.out.println(y);

x ^= (y ^= (x ^= y));

System.out.println(x);
System.out.println(y);

At this stage the output became 4, 3, 0, 4. Now I know that the 0 is a result of 4 ^ 4 because the x assignment wasn't complete at that time - why is this happening? Why doesn't the x ^= y actually assign 7 to the x variable so that it becomes 7 ^ 4 for the last assignment?

like image 893
Xsjado Avatar asked Aug 27 '15 08:08

Xsjado


People also ask

Is multiple assignment possible in C?

MultipleAssignment is a language property of being able to assign one value to more than one variables. It usually looks like the following: a = b = c = d = 0 // assigns all variables to 0.

What is multiple assignment illustrate with an example?

multiple assignment A form of assignment statement in which the same value is given to two or more variables. For example, in Algol, a := b := c := 0. sets a, b, c to zero. A Dictionary of Computing.

What is multiple assignment operator?

You can perform multiple assignments in the same SET statement. You can perform multiple assignments in the same statement. Unlike = , the := operator is never interpreted as a comparison operator. This means you can use := in any valid SQL statement (not just in SET statements) to assign a value to a variable.

Does Java support multiple assignment?

Java permits the use of multiple assignments in one statement. In such statements, the assignment operators are applied from right to left, rather than from left to right.


2 Answers

Let's try to expand your last expression.

It evaluates to,

x = x^(y = y^ (x = x^y));

Note that expressions are evaluated from left to right,

it becomes,

x = 4 ^ (y = 3 ^ (x = 4 ^ 3));

Now, the problem has become obvious. Right?

Edit:

To clear come confusion, let me try to explain what I mean by evaluating from left to right.

int i = 1;
s = i + (i = 2) + i;

Now, the expression will evaluate to,

s = 1 +    2    + 2;

Notice that i on the left of assignment was 1, but on the right of assignment (and on the assigment) was evaluated to 2, because the evaluation is from left to right, when it came to the 2nd and 3rd part of the expression, is value was 2.

like image 197
Codebender Avatar answered Oct 11 '22 07:10

Codebender


The order of evaluation is defined in chapter 15 of the JLS. Item 15.7.1 says:

If the operator is a compound-assignment operator (§15.26.2), then evaluation of the left-hand operand includes both remembering the variable that the left-hand operand denotes and fetching and saving that variable's value for use in the implied binary operation.

To explain further, they have two examples of computations that involve assignments. Here the assignment is on the left hand of the operator:

int i = 2;
int j = (i=3) * i;
System.out.println(j);

And they specifically say that the result is 9 and is not allowed to be 6. That is, the (i=3) is both calculated as 3 and i is assigned 3 before being multiplied with itself.

But in the second example:

    int a = 9;
    a += (a = 3);  // first example
    System.out.println(a);
    int b = 9;
    b = b + (b = 3);  // second example
    System.out.println(b);

The JLS specifies that both prints should produce 12, and are not allowed to produce 6. That is, because the assignment to b is on the right side, the value of the left b (or the implicit left a in the += operation), the value before that assignment is fetched and saved first, and only then the operation inside the parentheses is performed.

Internally, expressions are broken down into JVM operations that push and pop values onto an "operand stack". If you think about it like that - that in b = b + (b=3) The value of b is first pushed onto the operand stack, then the (b=3) is performed and its value is then added to the value popped from the stack (old value of b), it will make sense. At this point, the left hand b just stands for "What the value of b was when it was pushed on the stack" and not for the "current value of b".

like image 44
RealSkeptic Avatar answered Oct 11 '22 08:10

RealSkeptic