2010-10-03 5 views
0

Можно создать дубликат:
Potential Problem in “Swapping values of two variables without using a third variable”Этот трюк всегда работает?

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

m^= n^= m^= n; был упомянут трюк.

Что вы, ребята, думаете? Этот прием всегда полезен?

+2

Нет, это не так. Здесь вы найдете: http://stackoverflow.com/questions/3741440/potential-problem-in-swapping-values-of-two-variables-without-using-a-third-vari/3741450 – codaddict

ответ

0

Это чаще всего опасно (в вашем случае это на самом деле неопределенное поведение, плюс если одно число равно нулю, все идет не так). Если у вас недостаточно памяти в памяти, лучше просто использовать временную переменную (или функцию смены stl). Это более ясно, что вы делаете и проще в обслуживании.

5

так, как вы его написали, это неопределенное поведение. Это связано с тем, что вы изменяете переменную более одного раза в одной и той же точке последовательности. Однако, если вы перепишите его следующим образом:

m ^= n; 
n ^= m; 
m ^= n; 

тогда это безопасно. Однако «полезным» является еще один вопрос, он редко «полезен», а иногда он на самом деле медленнее, чем на самом деле, используя temp!

Также вам нужно быть осторожным с наложением (указатели/ссылки), потому что, если вы попытаетесь что-то поменять с собой, вы в конечном итоге случайно обнулите свою ценность. Например:

#define SWAP(m, n) { m ^= n; n ^= m; m ^= n; } 

int x[] = { 1, 2, 3, 4 }; 
int i = 0; 
int j = 0; 
SWAP(x[i], x[j]); // whoops, x[0] == 0 now, not 1! 

более традиционная реализация свопа не имеет этой проблемы.

3

Нет, это неопределенное поведение как на C, так и на C++. Иногда это может работать, но вы не должны полагаться на него.

Кроме того, даже «фиксированные» вариации не всегда работает:

m ^= n; 
n ^= m; 
m ^= n; 

Это не выполняется, если т и п ссылки на одной и той же переменной. В этом случае он устанавливает значение в ноль.

C не имеет ссылок, но даже в C есть еще опасность подстерегает, если вы пытаетесь использовать этот трюк:

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

    a[m] ^= a[n]; 
    a[n] ^= a[m]; 
    a[m] ^= a[n]; 
    

Теперь, если т == п снова значение от [m] устанавливается на ноль.

Пожалуйста, не используйте «умные» трюки, подобные этому. Используйте временную переменную для замены двух значений.

1

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

+0

Современные процессоры лучше работают с временный характер. Они могут выполнять два назначения параллельно, но они должны останавливаться для версии XOR. – GManNickG

+0

@GMan: Вы имеете в виду пару команд? Но какие задания можно спарить в этом случае? –

+0

@Nick: с 'int temp = x; x = y; y = temp; ', последние два. – GManNickG

Смежные вопросы