Трюк с обменом: a = b + (b = a) * 0;

a=b+(b=a)*0;

Это предложение может менять значение между a и b.
Я пробовал его с С#, и он работает.
Но я просто не знаю, как это работает.
например.

a = 1, b = 2

Я перечисляю следующие шаги:

b = a -> a = 1, b = 1
b * 0 -> a = 1, b = 1
b + 0 -> a = 1, b = 1
a = b -> a = 1, b = 1 ?

Но значение b может быть неправильным.
Может ли кто-нибудь мне помочь? Меня это сильно озадачивает.

Ответы

Ответ 1

a=b+(b=a)*0;

То, что (b=a) в середине является установкой оператора присваивания b текущему значению a с побочным эффектом, что его результат (окончательное значение) b. Когда это умножается на 0, вы получаете 0, но назначение все равно произошло.

Внешний бит устанавливает a в b плюс результат (b=a)*0 (который равен нулю). Поскольку исходный b уже использовался для начала установки a до назначения в бит (b=a), назначение не влияет на a. Другими словами, это атомный a = b; b = a;, заменяющий два значения.

С# оценивает вещи в строгом порядке слева направо (в отличие от C и С++), чтобы избежать большого класса тонких ошибок. Обратите внимание, что компилятор может оценивать их в другом порядке, но только если он может определить, что он не будет иметь эффекта (это не так).

Отсканированный вами фрагмент работает, но также является отвратительным и не очень хорошая идея, особенно если вы можете использовать гораздо более читаемые:

int t = a; a = b; b = t;

Трюки, как то, что вы видите здесь, и трюк с заменой XOR, и устройство Duff не имеют места в достойном, поддерживаемом коде. Обычно это способ, чтобы кодеры показывали, насколько они умны, но обычно показывают, насколько они плохи.

Если вы когда-нибудь увидите что-то подобное в производственном кодексе, я не думаю, что какое-либо жюри в мире обвинило бы вас в том, что вы охотитесь за преступником и избиваете их до смерти с помощью списка свернутых программ.

Вы должны написать свой код, как будто следующий человек, который должен его поддерживать, - это психопат, который знает, где вы живете, - в моем случае вы были бы наполовину правы - я понятия не имею, где вы живете: -)

Ответ 2

Тьфу! Где вы это видели? Я скорее привык к трюку (a ^ = b; b ^ = a; a ^ = b;), так что я, по крайней мере, его узнаю (НЕ СЛЕДУЕТ! Я НИКОГДА НЕ СКАЗАЛ, Я ИСПОЛЬЗУЮ ЭТО!), Но я "Мне нужно взглянуть на это на минуту... Если вы видели это в производственном коде, пожалуйста, выясните, кто его написал и причинил ему боль.

Как говорили другие (но я хотел бы подчеркнуть это): "a = b" - это назначение, но это также выражение со значением. Вот почему вы можете делать такие вещи, как "a = b = c = d" - это не трюк с особым случаем; они просто группируются как "a = (b = (c = d))", а значение "d" складывается обратно ко всем этим переменным.

Ответ 3

  0. a=b+(b=a)*0     |             | a = 1, b = 2
  1. Evaluate b      | a=2+(b=a)*0 | a = 1, b = 2
  2. Evaluate (b=a)  | a=2+1*0     | a = 1, b = 1
  3. Evaluate 1*0    | a=2+0       | a = 1, b = 1
  4. Evaluate 2+0    | a=2         | a = 1, b = 1
  5. Evaluate a=2    |             | a = 2, b = 1