给定两个数字a和b,要求不使用中间变量交换二者
一般做法
一般的做法很简单
|
不使用中间变量的做法
采用位操作符中的异或操作^
操作符 | 功能 | 用法 | |
---|---|---|---|
~ | 取反 | 0变1,1变0 | |
<< | 左移 | 后面补0 | |
>> | 右移 | 前面补0,后面吞位 | |
& | 位与 | 只有两个都为1,则为1。x&…00100…用于提取x某一位 | |
^ | 位异或 | 只有一个为1,则为 1。用于判断两位是否相同 a^b^a = b 用于交换数值 | |
\ | 位或 | 有一个或2个1,则为1。用于做and运算 |
容易发现^
的性质:
- 两个相同的数字做
^
操作得0 - 任何数字跟0做
^
操作还是它本身
所以可以通过下面的方式交换两个数字
|
这个程序大部分时间正确,但是有个致命缺陷,当a和b指向同一个位置时,计算a^b得0,也就是说a和b所指向的地址是同一个,所以此时a=b=0。所以上面这样写的前提是假设两个指针不会指向同一个位置。这也是编译器优化时经常考虑的一点,这种两个指针指向同一个存储器的情况叫做存储器别名使用(memory aliasing)。
因此正确的程序应该如下:void swap(int &a;int &b){ if (a!=b){ a = a^b; b = b^a; a = a^b; }}