a += b;
b = a - b;
a -= b;
Интересно разве что с академической точки зрения. Но есть способ интереснее:a ^= b ^= a ^= b;
который также меняет местами значения этих переменных.Update: В комментариях подсказали грамотную ссылку по трюкам с битовой арифметикой.
Уточнил бы язык. Может, на каком-то C# это и прокатит, но на C/C++ - это unspecified behavior
ОтветитьУдалитьwecanstoptrain, тогда разбей на три операции=)
ОтветитьУдалитьwecanstoptrain: Язык С/C++. А почему unspecified behavior? Операции присваивания выполняются справа налево. Точно также, как бы они были записаны в три строки.
ОтветитьУдалитьВернее undefined:
ОтветитьУдалитьhttp://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#351
Александр: Да, операции выполняются справа налево, но стандарт не определяет, что будет лежать в переменной "a" после выполнения данного выражения.
ОтветитьУдалитьздесь все разжевано:
http://alenacpp.blogspot.com/2005/11/sequence-points.html
Да, похоже лучше в одну строчку не писать. Спасибо за совет.
ОтветитьУдалитьПервый вариант, кстати, не гарантирует выполнение операции если а = 32767
ОтветитьУдалитьxander_prowler: Первый пример чисто книжный.
ОтветитьУдалитьПопался мне этот вопрос на интервью. Только формулировка была другой: "Как поменять содержимое двух ячеек, не используя третьей?" Индус с гордостью показал мне арифметическое решение, после чего я доказал что на самом деле эти операции задействуют больше двух ячеек (дебаг на ассемблере все объясняет).
ОтветитьУдалитьВот ещё интересные способы:
ОтветитьУдалитьhttp://graphics.stanford.edu/~seander/bithacks.html#SwappingValuesSubAdd
Отличная ссылка, спасибо.
ОтветитьУдалитьxander_prowler, никакой разницы нет вроде. С этим проблемы могут быть только в джаве имхо . . . Ведь переменные "зациклены" так сказать.
ОтветитьУдалитьchar a = 127, b = 28;
a = a + b; // станет a = -101, b = 28
b = a - b; // станет a = -101, b = 127
a = a - b; // станет a = 28, b = 128
Ведь signed/unsigned - всего лишь способ трактовки двоичного значения. А операции + и - выполняются именно для двоичных значений.
Александр, время от времени почитываю там некоторые бит-хаки)) Работают мгновенно.
ОтветитьУдалитьxander_prowler, кстати считал в calc.exe в Win7))
ОтветитьУдалитьТам теперь есть режим "Программист".
Пруфпик: http://yfrog.com/jw123rmp
Первый пример грозит целочисленным переполнением.
ОтветитьУдалитьЕсли a и b -- это ссылки на одну и ту же переменную, то приведённый код (я о втором варианте) обнулит её. В общем, я бы дважды подумал перед тем, как использовать такое на практике.
ОтветитьУдалитьi1ey: Да, проверить на то, что а и b разные переменные не мешает, но это критично для любой функции обмена. В большинстве случаев разумно проверить, чтобы не гонять данные впустую.
ОтветитьУдалитьПрикольно, конечно, но зачем ?
ОтветитьУдалитьНапомнило "изврат" с определением минимального из двух чисел:
min (a, b) ::= (a + b - ABS (a - b))/2
Конечно, if не используется, но каково придется тому, кто такое будет потом читать :)
Но, видали. А как думаете (а может кто опыт ставил) по производительности какой из трёх вариантов победит? (третий с дополнительной переменной)
ОтветитьУдалитьна питоне получилось так (меньше — быстрее):
ОтветитьУдалитьс использованием разницы/суммы - 74 у.е.
с использованием третьей переменной - 47 у.е.
с использованием xor - 81 у.е.
Может, конечно, особенности питона. Надо попробовать на сях.
http://wmate.ru/ebooks/book237.html
ОтветитьУдалить