Подтвердить что ты не робот

Несколько назначений на одну строку не работают как ожидалось

Я пытаюсь поменять местами два int - x и y в примере и сделать это в одной строке без библиотечной функции.

Итак, я начал с этого:

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);

Вывод был 4, 3, 7, 3, 7, 4, 3, 4, как ожидалось. Все хорошо до сих пор.

Далее было следующее:

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);

Результат был 4, 3, 7, 4, 3, 4, как и ожидалось еще раз. До сих пор хорошо.

Тогда, наконец, это:

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);

На этом этапе выход стал 4, 3, 0, 4. Теперь я знаю, что 0 является результатом 4 ^ 4, потому что назначение x в то время не было полным - почему это происходит? Почему x ^= y не присваивает 7 переменной x, чтобы она стала 7 ^ 4 для последнего назначения?

4b9b3361

Ответ 1

Попробуйте расширить ваше последнее выражение.

Он оценивает,

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

Обратите внимание, что выражения оцениваются от слева до справа,

он становится,

x = 4 ^ (y = 3 ^ (x = 4 ^ 3));

Теперь проблема стала очевидной. Правильно?

Изменить:

Чтобы устранить путаницу, позвольте мне попытаться объяснить, что я имею в виду, оценивая слева направо.

int i = 1;
s = i + (i = 2) + i;

Теперь выражение будет оценивать,

s = 1 +    2    + 2;

Обратите внимание, что i в левом присваивания было 1, но при назначении справа (и в настройке) было оценено значение 2, потому что оценка выполняется слева направо, когда она попадает во вторую и третью части выражения, значение i было 2.

Ответ 2

Порядок оценки определяется в главе 15 JLS. Элемент 15.7.1 говорит:

Если оператор является оператором составного присваивания (§15.26.2), то оценка левого операнда включает в себя как запоминание переменной, которую левый операнд обозначает, так и выборку и сохранение этого значения переменной для использования в подразумеваемая двоичная операция.

Чтобы объяснить далее, у них есть два примера вычислений, которые включают в себя назначения. Здесь задание находится слева от оператора:

int i = 2;
int j = (i=3) * i;
System.out.println(j);

И они специально говорят, что результат равен 9, и ему не разрешено быть 6. То есть (i = 3) вычисляется как 3, а я присваивается 3 перед умножением на себя.

Но во втором примере:

    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);

JLS указывает, что обе распечатки должны выдавать 12, и не разрешено создавать 6. То есть, поскольку назначение b находится с правой стороны, значение слева b (или неявное левое a в операции +=), значение перед этим присваиванием выбирается и сохраняется сначала, и только тогда выполняется операция внутри круглых скобок.

Внутри выражения разбиваются на операции JVM, которые вызывают и вытесняют значения в "стек операнда". Если вы так думаете об этом - это в b = b + (b=3) Значение b сначала помещается в стек операнда, затем выполняется (b = 3), и его значение затем добавляется к значению, выбитому из стека ( старое значение b), это будет иметь смысл. В этот момент левая рука b просто означает "Что такое значение b, когда оно было нажато в стеке", а не "текущее значение b".

Ответ 3

Позволяет делить и вычислять.

Самая внутренняя скобка выполняется первой, и после того, как все скобки разрешены, выражение выполняется слева направо.

x ^= (y ^= (x ^= y));   // initial statement

x = x^(y = y^ (x = x^y)); //equals to 

() have the highest precedence

x = x^(y = y^ (x = 3^4)); // first highest precedence () 

x = x^(y = y ^ (x = 7)); // still the first x is 3

x = 4 ^(y = 3 ^ (x = 7));  // now 3 ^ 7 =4

x = 4 ^ 4;  // now  3 ^ 7 =4

x= 0;