14
int x=1;
int y=2;
x ^= y ^= x ^= y;

I am expecting the values to be swapped.But it gives x=0 and y=1. when i tried in C language it gives the correct result.

Hungry Blue Dev
  • 1,313
  • 16
  • 30
sadananda salam
  • 845
  • 1
  • 7
  • 12

2 Answers2

57

Your statement is roughly equivalent to this expanded form:

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

Unlike in C, in Java the left operand of a binary operator is guaranteed to be evaluated before the right operand. Evaluation occurs as follows:

x = x ^ (y = y ^ (x = x ^ y))
x = 1 ^ (y = 2 ^ (x = 1 ^ 2))
x = 1 ^ (y = 2 ^ (x = 3))
x = 1 ^ (y = 2 ^ 3)             // x is set to 3 
x = 1 ^ (y = 1)
x = 1 ^ 1                       // y is set to 1
x = 0                           // x is set to 0

You could reverse the order of the arguments to each xor expression so that the assignment is done before the variable is evaluated again:

x = (y = (x = x ^ y) ^ y) ^ x
x = (y = (x = 1 ^ 2) ^ y) ^ x
x = (y = (x = 3) ^ y) ^ x 
x = (y = 3 ^ y) ^ x             // x is set to 3
x = (y = 3 ^ 2) ^ x
x = (y = 1) ^ x
x = 1 ^ x                       // y is set to 1
x = 1 ^ 3
x = 2                           // x is set to 2

This is a more compact version that also works:

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

But this is a truly horrible way to swap two variables. It's a much better idea to use a temporary variable.

Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
  • Are you sure? I thought an assignment returned true, which is why if statements where = was used instead of == always ran? That'd mean your first statement was the same as x=x^true^true; – AaronM Oct 02 '10 at 22:38
  • 1
    @Aaron, no. JLS [§15.26](http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.26): "At run time, the result of the assignment expression is the value of the variable after the assignment has occurred." In Java, the old `=` instead of `==` in an `if` condition only compiles if the variable is a boolean. – Matthew Flaschen Oct 02 '10 at 22:54
15

Mark is completely correct about how it evaluates in Java. The reason is JLS §15.7.2., Evaluate Operands before Operation, and §15.7, which requires evaluation left to right:

It is equivalent (by §15.26.2, Compound Assignment Operators) to:

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

We evaluate left to right, doing both operands before the operation.

x = 1 ^ (y = y ^ (x = (x ^ y))); // left of outer 
x = 1 ^ (y = 2 ^ (x = (x ^ y))); // left of middle 
x = 1 ^ (y = 2 ^ (x = (1 ^ y))); // left of inner
x = 1 ^ (y = 2 ^ (x = (1 ^ 2))); // right of inner
x = 1 ^ (y = 2 ^ (x = 3)); // inner xor (right inner assign)
x = 1 ^ (y = 2 ^ 3); // inner assign (right middle xor)
x = 1 ^ (y = 1); // middle xor (right middle assign)
x = 1 ^ 1; // middle assign (right outer xor)
x = 0; // outer xor (right outer assign)

Note that it is undefined behavior in C, because you're modifying the same variable twice between sequence points.

Matthew Flaschen
  • 278,309
  • 50
  • 514
  • 539