I'm trying to swap two int
s - 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?
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.
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.
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.
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.
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?
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, i
s value was 2
.
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".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With