昨天,我看到了以下功能。
static void swap (int *p, int *q) {
*p -= *q;
*q += *p;
*p = *q - *p;
}
在哪种情况下此功能不起作用?我认为可能存在溢出问题,而且效率也很低。还有别的吗?
答案 0 :(得分:4)
溢出问题不是“可能”,它肯定存在:当你用一个大的正数交换一个高幅度的负数时,你会得到溢出,这是根据标准的未定义行为。
但最重要的是,出于可读性的原因,绝对没有必要使用这个(或xor技巧)代替通常的交换(通过临时变量)。
答案 1 :(得分:1)
实际上上面的答案是错误的。对于p,它得到0xFFFFFFFE,因为它用0x7FFFFFFFE初始化q,这不适合并且(除了未定义的行为)实际上被截断为0xFFFFFFFE。
因此,该答案中的代码实际上以p = 0xFFFFFFFF和q = 0xFFFFFFFE开头并成功交换它们。
(编辑:它错了,现在已经纠正了)
该例程实际上工作得很好(除了最终未定义的行为,我不确定是否存在,我对标准的细节有点模糊)。
忽略最终的未定义行为,如果基础算术是常见的2的补码模运算,则该例程可以正常运行并且没有溢出/下溢的问题(它是模运算)。
唯一真正的问题是别名。如果两个指针相同,则指向整数将变为0.
因此,例程的前提条件是两个指针有效且没有别名。如果这是您期望程序需要的,则可以添加对空指针和相同指针的检查。
为什么要使用这种机制而不是xor技巧而不是临时变量交换的问题仍然存在。但是没有与OP问题有关:例程工作和溢出,因为它由2的补码模运算处理,这是处理器上最常见的,不是问题(编辑:它只是因为溢出是未定义的行为标准,但它适用于任何使用2的补码模运算的处理器。至于效率,这一切都取决于优化器和处理器。