从初高中的OI到大学中的ACM,队友中都流传着交换变量用位运算要比用赋值速度快。不少人对此深信不疑。但这真的是真的么?今天就来从理论上分析这个问题的真假。
先附上今天所要测试的程序段:
编译环境:
1 | ➜ test clang --version |
先是赋值交换
1 | void swap(int *a, int *b) |
然后是位运算交换
1 | void swap(int *a,int *b) |
由于这里只是程序片段,就不再生成可执行文件。使用clang编译获得汇编文件来进行对比。
首先,我们不开编译优化,看看编译后的结果。(clang %s.c -S -o %s-no.s -m32
)
赋值交换:
1 | .section __TEXT,__text,regular,pure_instructions |
位运算交换:
1 | .section __TEXT,__text,regular,pure_instructions |
很明显,赋值交换的指令数量已经比位运算交换少了不少。(待补充汇编代码分析)下面我们再打开第一级编译优化(clang %s.c -S -o %s-o1.s -O -m32
)来试一下:
赋值交换:
1 | .section __TEXT,__text,regular,pure_instructions |
位运算交换:
1 | .globl _swap |
赋值发在完成两个方法相同的寄存器变量准备步骤后,赋值法仅用了两个mov指令就完成了变量交换。而位运算法执行了三个xor两个mov指令才完成交换。
因此,位运算交换两数并不比赋值法快,特别在编译优化优秀的编译器上,中间变量完全可以使用寄存器优化掉。因此,放弃用位运算作交换的念头吧。