int x=1;
int y=2;
x ^= y ^= x ^= y;
Я ожидаю, что значения будут заменены. Но это дает x = 0 и y = 1. когда я пытаюсь на языке C, он дает правильный результат.
int x=1;
int y=2;
x ^= y ^= x ^= y;
Я ожидаю, что значения будут заменены. Но это дает x = 0 и y = 1. когда я пытаюсь на языке C, он дает правильный результат.
Ваше утверждение примерно эквивалентно этой расширенной форме:
x = x ^ (y = y ^ (x = x ^ y));
В отличие от C, в Java левый операнд двоичного оператора гарантированно оценивается перед правильным операндом. Оценка происходит следующим образом:
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
Вы можете изменить порядок аргументов на каждое выражение xor, чтобы выполнить назначение перед повторной оценкой переменной:
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
Это более компактная версия, которая также работает:
x = (y ^= x ^= y) ^ x;
Но это поистине ужасный способ поменять две переменные. Намного лучше использовать временную переменную.
Марк полностью прав, как он оценивается на Java. Причина заключается в том, что JLS §15.7.2., оценивать операнды до операции и §15.7, который требует оценки слева направо:
Это эквивалентно (§15.26.2, Операторы присвоения назначений):
x = x ^ (y = y ^ (x = (x ^ y)));
Мы оцениваем слева направо, делая оба операнда до операции.
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)
Обратите внимание, что это поведение undefined в C, потому что вы дважды изменяете одну и ту же переменную между точками последовательности.