另一种交换两个变量内容的方式?

时间:2012-09-15 12:39:07

标签: c pointers swap

昨天,我看到了以下功能。

static void swap (int *p, int *q) {
    *p -= *q;
    *q += *p;
    *p = *q - *p;
}

在哪种情况下此功能不起作用?我认为可能存在溢出问题,而且效率也很低。还有别的吗?

2 个答案:

答案 0 :(得分:4)

溢出问题不是“可能”,它肯定存在:当你用一个大的正数交换一个高幅度的负数时,你会得到溢出,这是根据标准的未定义行为。

但最重要的是,出于可读性的原因,绝对没有必要使用这个(或xor技巧)代替通常的交换(通过临时变量)。

答案 1 :(得分:1)

实际上上面的答案是错误的。对于p,它得到0xFFFFFFFE,因为它用0x7FFFFFFFE初始化q,这不适合并且(除了未定义的行为)实际上被截断为0xFFFFFFFE。

因此,该答案中的代码实际上以p = 0xFFFFFFFF和q = 0xFFFFFFFE开头并成功交换它们。

(编辑:它错了,现在已经纠正了)

该例程实际上工作得很好(除了最终未定义的行为,我不确定是否存在,我对标准的细节有点模糊)。

忽略最终的未定义行为,如果基础算术是常见的2的补码模运算,则该例程可以正常运行并且没有溢出/下溢的问题(它是模运算)。

唯一真正的问题是别名。如果两个指针相同,则指向整数将变为0.

因此,例程的前提条件是两个指针有效且没有别名。如果这是您期望程序需要的,则可以添加对空指针和相同指针的检查。

为什么要使用这种机制而不是xor技巧而不是临时变量交换的问题仍然存在。但是没有与OP问题有关:例程工作和溢出,因为它由2的补码模运算处理,这是处理器上最常见的,不是问题(编辑:它只是因为溢出是未定义的行为标准,但它适用于任何使用2的补码模运算的处理器。至于效率,这一切都取决于优化器和处理器。