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.

13
  • 4
    It's undefined behavior in C, since you're modifying both x and y twice in a sequence point. Commented Oct 2, 2010 at 8:32
  • 3
    Dont use it. Using an extra temp variable to swap 2 is MUCH more efficient because it doesnt have to make the computation. Commented Oct 2, 2010 at 8:35
  • 2
    Behaviour of the expression x ^= y ^= x ^= y; is undefined in C. Commented Oct 2, 2010 at 8:40
  • 2
    IMre L: you are completely wrong. Just because the "computation" takes longer for us humans, there is no reason to assume that it will take longer than an assingment on a computer. In fact, I bet both will take exactly as long. XOR is about the most trivial operation a CPU can do. Commented Oct 2, 2010 at 9:32
  • 2
    The wording "correct" is incorrect. Commented Oct 2, 2010 at 10:23

2 Answers 2

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.

Sign up to request clarification or add additional context in comments.

2 Comments

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;
@Aaron, no. JLS §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.
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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.