I tried some code to swap two integers in Java without using a 3rd variable, using XOR.
Here are the two swap functions I tried:
package lang.numeric;
public class SwapVarsDemo {
public static void main(String[] args) {
int a = 2984;
int b = 87593;
swapDemo1(a,b);
swapDemo2(a,b);
}
private static void swapDemo1(int a, int b) {
a^=b^=a^=b;
System.out.println("After swap: "+a+","+b);
}
private static void swapDemo2(int a, int b) {
a^=b;
b^=a;
a^=b;
System.out.println("After swap: "+a+","+b);
}
}
The output produced by this code was this:
After swap: 0,2984
After swap: 87593,2984
I am curious to know, why is this statement:
a^=b^=a^=b;
different from this one?
a^=b;
b^=a;
a^=b;
The issue is the order of evaluation:
See JLS section 15.26.2
First, the left-hand operand is evaluated to produce a variable. If this evaluation completes abruptly, then the assignment expression completes abruptly for the same reason; the right-hand operand is not evaluated and no assignment occurs.
Otherwise, the value of the left-hand operand is saved and then the right-hand operand is evaluated. If this evaluation completes abruptly, then the assignment expression completes abruptly for the same reason and no assignment occurs.
Otherwise, the saved value of the left-hand variable and the value of the right-hand operand are used to perform the binary operation indicated by the compound assignment operator. If this operation completes abruptly, then the assignment expression completes abruptly for the same reason and no assignment occurs.
Otherwise, the result of the binary operation is converted to the type of the left-hand variable, subjected to value set conversion (§5.1.13) to the appropriate standard value set (not an extended-exponent value set), and the result of the conversion is stored into the variable.
So your expression does:
a^=b^=a^=b;
a
b^=a^=b
a
in step one does not have ^=b
applied to it yet)a
In other words, your expression is equivalent to the following java code:
int a1 = a;
int b2 = b;
int a3 = a;
a = a3 ^ b;
b = b2 ^ a;
a = a1 ^ b;
You can see that from the disassembled version of your method:
private static void swapDemo1(int, int);
Code:
0: iload_0
1: iload_1
2: iload_0
3: iload_1
4: ixor
5: dup
6: istore_0
7: ixor
8: dup
9: istore_1
10: ixor
11: istore_0
Because a ^= b ^= a ^= b;
is parsed like:
a ^= (b ^= (a ^= b));
Which can be reduced to:
a ^= (b ^= (a ^ b));
So b
will have the value b ^ (a ^ b)
and finally a
will be a ^ (b ^ (a ^ 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