四中方法:临时变量 ,算术运算,位运算,指针地址操作
1.临时变量 (简单易懂,推荐使用)
temp=a; //a,temp,b均为变量。a,b为要交换的两个变量
a=b;
b=temp;
2.算术运算
a=b-a;b=b-a;
a=b+a;
3.位运算 / 异或运算(很神奇,但是确实行)
a=a^b;
b=a^b;
a=a^b;
4.指针地址操作 (c语言,特定平台,不易理解,效率很高)
对地址的操作实际上进行的是整数运算,比如:两个地址相减得到一个整数,表示两个变量在内存中的储存位置隔了多少个字节;地址和一个整数相加即“a+10”表示以a为基地址的在a后10个a类数据单元的地址。所以理论上可以通过和算术算法类似的运算来完成指针指向的地址的变换。
int *a,*b;*a=new int(10);
*b=new int(20); //&a=0x00001000h,&b=0x00001200h
a=(int*)(b-a); //&a=0x00000200h,&b=0x00001200h
b=(int*)(b-int(a)); //&a=0x00000200h,&b=0x00001000h
a=(int*)(b+int(a)); //&a=0x00001200h,&b=0x00001000h
原理是这样的,但是结果不对。???(
首先必须了解,操作系统把内存分为几个区域:系统代码/数据区、应用程序代码/数据区、堆栈区、全局数据区等等。在编译源程序时,常量、全局变量等都放入全局数据区,局部变量、动态变量则放入堆栈区。这样当算法执行到“a=(int*)(b-a)”时,a的值并不是0x00000200h,而是要加上变量a所在内存区的基地址,实际的结果是:0x008f0200h,其中0x008f即为基地址,0200即为a在该内存区的位移。它是由编译器自动添加的。因此导致以后的地址计算均不正确,使得a,b指向所在区的其他内存单元。再次,地址运算不能出现负数,即当a的地址大于b的地址时,b-a<0,系统自动采用补码的形式表示负的位移,由此会产生错误,导致与前面同样的结果。 )
改进后如下:
if(a<b)
{
a=(int*)(b-a);
b=(int*)(b-(int(a)&0x0000ffff));
a=(int*)(b+(int(a)&0x0000ffff));
}
else
{
b=(int*)(a-b);
a=(int*)(a-(int(b)&0x0000ffff));
b=(int*)(a+(int(b)&0x0000ffff));
}
采用位运算中的与运算“int(a)&0x0000ffff”,高16位为段地址,低16位为位移地址,和0x0000ffff进行与运算后,段地址被屏蔽,只保留位移地址。
本文只是从算法和程序设计的角度介绍了4中交换变量的方法,目的是为了开拓思维,训练逻辑,真正的实践中推荐使用第一种临时变量法。