使用异或运算交换两个整数

一般来说,我们可以用异或运算来交换两个整数,这样可以避免在交换的过程中用到临时变量。(其实用到一个临时变量也不影响程序性能,所以此处无非是编程技巧的考察了。)

代码可以这样写:

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马上就借位了,把不该进的位恢复了。所以溢出不会对交换的结果造成影响,程序正常工作。

posted @ 2014-10-31 15:20  nipan  阅读(2464)  评论(0编辑  收藏  举报