Это уравнение меняет местами два числа без временной переменной, но использует арифметические операции:
a = (a+b) - (b=a);
Как обойтись без арифметических операций? Я думал о XOR.
Это уравнение меняет местами два числа без временной переменной, но использует арифметические операции:
a = (a+b) - (b=a);
Как обойтись без арифметических операций? Я думал о XOR.
a=a+b;
b=a-b;
a=a-b;
Это просто, но эффективно ....
a=a+b
. Затем произойдет два недополнения в b=a-b
и a=a-b
, в результате чего обе переменные правильно меняют местами значения.
- person displayName; 03.11.2015
В C это должно работать:
a = a^b;
b = a^b;
a = a^b;
ИЛИ круче / увлекательнее на вид:
a^=b;
b^=a;
a^=b;
Дополнительные сведения см. В этом. XOR - очень мощная операция, у которой то тут, то там возникает много интересных применений.
std::swap
.) Вот и все. В чем смысл этого вопроса? У вас есть актуальная проблема?
- person GManNickG; 05.09.2010
a ^= b ^= a ^= b
(или, что еще хуже, a^=b^(b=a)
)
- person Tim; 19.10.2015
Почему бы не использовать стандартные библиотеки?
std::swap(a,b);
Лучший способ поменять местами два числа без использования какого-либо временного хранилища или арифметических операций - это загрузить обе переменные в регистры, а затем использовать регистры наоборот!
Вы не можете сделать это непосредственно из C, но компилятор, вероятно, вполне способен решить это за вас (по крайней мере, если включена оптимизация) - если вы напишете простой, очевидный код, такой как тот, который Кенни предложил в своем комментарии .
e.g.
void swap_tmp(unsigned int *p)
{
unsigned int tmp;
tmp = p[0];
p[0] = p[1];
p[1] = tmp;
}
скомпилированный с помощью gcc 4.3.2 с флагом оптимизации -O2
дает:
swap_tmp:
pushl %ebp ; (prologue)
movl %esp, %ebp ; (prologue)
movl 8(%ebp), %eax ; EAX = p
movl (%eax), %ecx ; ECX = p[0]
movl 4(%eax), %edx ; EDX = p[1]
movl %ecx, 4(%eax) ; p[1] = ECX
movl %edx, (%eax) ; p[0] = EDX
popl %ebp ; (epilogue)
ret ; (epilogue)
Используя XOR,
void swap(int &a, int &b)
{
a = a ^ b;
b = a ^ b;
a = a ^ b;
}
Один лайнер с XOR,
void swap(int &a, int &b)
{
a ^= b ^= a ^= b;
}
Эти методы кажутся чистыми, потому что они не терпят неудачу ни в одном тестовом примере, но, опять же, поскольку (как и в методе 2) значение переменной изменяется дважды в одной и той же точке последовательности, говорят, что оно имеет неопределенное поведение, объявленное ANSI C.
Я раньше не видел этого решения C, но уверен, что кто-то об этом подумал. И, возможно, у меня было больше самоконтроля, чем у меня.
fprintf(fopen("temp.txt", "w"), "%d", a);
a = b;
fscanf(fopen("temp.txt", "r"), "%d", &b);
Никаких лишних переменных!
У меня это работает, но в зависимости от реализации stdio вам, возможно, придется что-то делать с буферизацией вывода.
В дополнение к приведенным выше решениям для случая, когда, если одно из значений выходит за пределы диапазона для целого числа со знаком, два значения переменных можно поменять местами таким образом
a = a+b;
b=b-(-a);
a=b-a;
b=-(b);
Также можно использовать умножение и деление.
int x = 10, y = 5;
// Code to swap 'x' and 'y'
x = x * y; // x now becomes 50
y = x / y; // y becomes 10
x = x / y; // x becomes 5
a
, иb
читаются и записываются без промежуточной точки последовательности. Во-первых, компилятор имеет право оцениватьb=a
перед тем, как оцениватьa+b
. - person Steve Jessop   schedule 05.09.2010b
. Нельзя полагаться на то, как компилятор отображает эту строку (если он вообще ее отображает). - person dmckee --- ex-moderator kitten   schedule 06.09.2010