使用异或运算交换两个整数
一般来说,我们可以用异或运算来交换两个整数,这样可以避免在交换的过程中用到临时变量。(其实用到一个临时变量也不影响程序性能,所以此处无非是编程技巧的考察了。)
代码可以这样写:
1 void 2 Swap(int *a, int *b) 3 { 4 5 *a ^= *b; 6 *b ^= *a; 7 *a ^= *b; 8 }
还有一种依赖于编译环境的写法,不一定在每种环境下都能完成交换的功能,是这样写的:
1 void 2 Swap(int *a, int *b) 3 { 4 *a ^= *b ^= *a ^= *b; 5 }
但是当我们碰到a和b是指向同一个地址的指针的时候,上述程序就会出错。比如一个数组a[2]={1, 2},我们Swap(&a[0], &a[1]),能正常完成交换。但是如果我们Swap(&a[0], &a[0]),则在*a ^= *b执行的时候,结果是*a = a[0]&a[0],为0,与此同时程序中的b其实跟a指向同一个地址,所以*b也成了0,所以这个Swap函数将a[0]置0了。
于是,我们在使用这个函数之前,首先要判断传入的两个指针是否指向同一个地址:
1 void 2 Swap(int *a, int *b) 3 { 4 if (a != b) { 5 *a ^= *b; 6 *b ^= *a; 7 *a ^= *b; 8 } 9 }
其实还有一种无须用到临时变量就能交换两个数的方法:
1 void 2 Swap(int *a, int *b) 3 { 4 *a = *a + *b; 5 *b = *a - *b; 6 *a = *a - *b; 7 }
呵呵:)
那么,如果上面这个程序中,a和b都相当大,那么会造成*a+*b溢出,而使得结果错误不能正确交换的情况吗?
不会的。因为在计算机中,溢出就是出现了进位(或借位)进到了不该进的地方,使得结果不能正确输出。然而在第一步溢出之后,第二步*a-*b马上就借位了,把不该进的位恢复了。所以溢出不会对交换的结果造成影响,程序正常工作。