Трюк со свопом: a = b + (b = a) * 0; - PullRequest
15 голосов
/ 05 августа 2011
a=b+(b=a)*0;

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

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 может быть неправильнымКто-нибудь может мне помочь?Это меня очень озадачивает.

Ответы [ 3 ]

19 голосов
/ 05 августа 2011
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 # оценивает вещи в строгом порядке слева направо (в отличие от C и C ++), чтобы избежать большого класса тонких ошибок.Обратите внимание, что компилятор может оценивать их в другом порядке, но только если он может определить, что он не будет иметь никакого эффекта (здесь это не так).

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

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

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

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

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

4 голосов
/ 05 августа 2011

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

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

3 голосов
/ 05 августа 2011
  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
...