我试图在不使用C的tmp的情况下编写交换功能,这就是我正在使用的内容:
void swap(int *a, int* b) {
*a += *b;
*b = *a - *b;
*a -= *b;
}
现在有一个问题(或者我认为是),如果*a + * b > INT_MAX
可能会溢出。令人困惑的是,即使在边缘情况下,它实际上也可以正常工作。有人可以解释为什么吗?
以下是我使用的一些测试用例:
int main() {
int t1Swap[] = {INT_MAX, 1};
int t2Swap[] = {INT_MAX, INT_MIN};
int t3Swap[] = {INT_MAX, INT_MAX-1000};
int t4Swap[] = {INT_MIN, INT_MIN+1000};
}
谢谢!
答案 0 :(得分:5)
带符号整数溢出是未定义的行为,因此它可能会起作用,也可能不会起作用,这取决于您的特定系统和编译器。为避免这种未定义的行为,请使用按位XOR运算符而不是加减运算符来交换变量,而无需引入temp
:
a=a^b;
b=a^b;
a=a^b;
答案 1 :(得分:2)
您可以像这样使用XOR;
void swap(int *a, int *b)
{
if (*a != *b)
{
*a^=*b;
*b^=*a;
*a^=*b;
}
}
答案 2 :(得分:2)
即使整数溢出在技术上是未定义的行为,但通常会回绕到INT_MIN。在这种情况下,您的算术实现可以工作(但不能移植)。
答案 3 :(得分:2)
如果您的目标是生成尽可能快的代码(或节省一些内存),那么棘手的XOR或add方法不是最佳选择:
考虑:
void swap1(int *a, int *b)
{
*a=*a^*b;
*b=*a^*b;
*a=*a^*b;
}
void swap2(int *a, int *b)
{
int c = *a;
*a = *b;
*b = c;
}
及其结果代码: X86
swap1:
mov eax, DWORD PTR [rdi]
xor eax, DWORD PTR [rsi]
mov DWORD PTR [rdi], eax
xor eax, DWORD PTR [rsi]
mov DWORD PTR [rsi], eax
xor DWORD PTR [rdi], eax
ret
swap2:
mov eax, DWORD PTR [rdi]
mov edx, DWORD PTR [rsi]
mov DWORD PTR [rdi], edx
mov DWORD PTR [rsi], eax
ret
因此,没有temp变量,您不会节省任何内存,但是会使算法变慢。有什么意义?