РЕДАКТИРОВАТЬ: Хорошо, понял.
Первое, на что нужно обратить внимание, это то, что вы, очевидно, не должны использовать этот код в любом случае. Однако, когда вы расширяете его, оно становится эквивалентным:
j = j ^ (i = i ^ (j = j ^ i));
(Если бы мы использовали более сложное выражение, такое как foo.bar++ ^= i
, было бы важно, чтобы ++
оценивалось только один раз, но здесь я считаю, что это проще.)
Теперь порядок вычисления операндов всегда слева направо, поэтому для начала получим:
j = 36 ^ (i = i ^ (j = j ^ i));
Это (выше) самый важный шаг. В итоге мы получили 36 в качестве LHS для операции XOR, которая выполняется последней. LHS не является «значением j
после оценки RHS».
Оценка RHS для ^ включает в себя «одноуровневое» выражение, поэтому оно становится:
j = 36 ^ (i = 25 ^ (j = j ^ i));
Затем, глядя на самый глубокий уровень вложенности, мы можем заменить i
и j
:
j = 36 ^ (i = 25 ^ (j = 25 ^ 36));
... который становится
j = 36 ^ (i = 25 ^ (j = 61));
Первоначально присваивается j
в RHS, но результат все равно перезаписывается в конце, поэтому мы можем игнорировать это - дальнейших оценок j
до окончательного присвоения нет:
j = 36 ^ (i = 25 ^ 61);
Теперь это эквивалентно:
i = 25 ^ 61;
j = 36 ^ (i = 25 ^ 61);
Или:
i = 36;
j = 36 ^ 36;
Что становится:
i = 36;
j = 0;
Я думаю это все правильно, и он получает правильный ответ ... извинения Эрику Липперту, если некоторые детали о порядке оценки немного не соответствуют: (