这个技巧总能奏效吗?

时间:2010-10-03 08:19:54

标签: c++ c

  

可能重复:
  Potential Problem in “Swapping values of two variables without using a third variable”

我最近在社区中读到,我们可以轻松地交换两个数字,而不使用第三个使用XOR技巧。

立方公尺= N ^ =立方公尺= N;提到了诀窍。

你们觉得怎么样?这个技巧总是有用吗?

4 个答案:

答案 0 :(得分:5)

你写它的方式,它是未定义的行为。这是因为您在同一序列点中多次修改变量。但是,如果您按如下方式重写它:

m ^= n;
n ^= m;
m ^= n;
那么它是安全的。然而,“有用”是另一个问题,它很少“有用”,有时它实际上比实际使用临时更慢!

此外,你需要小心别名(指针/引用),因为如果你试图与自己交换东西,那么你最终会意外地将你的值归零。例如:

#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!

更传统的交换实现没有这个问题。

答案 1 :(得分:3)

不,它在C和C ++中都是未定义的行为。它有时可能会起作用,但你不应该依赖它。

即使是“固定”变体也不总是有效:

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

如果m和n是对同一变量的引用,则会失败。在这种情况下,它将值设置为零。

C没有引用,但即使在C中,如果你试图使用这个技巧,仍然存在潜伏危险:

  • 您可以尝试将“工作”版本放入宏SWAP中,但如果使用SWAP(x,x)调用,将x始终设置为零,则可能会失败。
  • 您可以尝试扩展技巧以交换数组中的两个值,但如果您使用相同的索引,这可能会失败:

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

现在,如果m == n,则再次将[m]的值设置为零。

请不要使用这样的“聪明”技巧。使用临时变量来交换两个值。

答案 2 :(得分:1)

通过该技巧,您可以节省额外的内存位置以保存临时值。 它可能对整数有效,但是可读吗?您的上一代优化器也可以这样做。

答案 3 :(得分:0)

这通常更具危险性(在您的情况下,它实际上是未定义的行为;加上如果一个数字为零,则出现问题)。除非你的内存严重不足,否则最好只使用临时变量(或stl交换函数)。这更清楚你正在做什么,更容易维护。