交换两个数的一种方法:使用异或
开始
直接切入正题,一般不有特殊要求的时候,会通过借助一个临时变量的方法来实现。
而有些解决方案里是这样的
a = a ^ b; b = a ^ b; a = a ^ b;
应用时的优劣,可能需要从底层实现(比如反汇编?) 或者编译器的角度来认识。
从时间(创建、销毁成本)和空间的角度来理解
临时变量的创建是在栈上分配空间,是“栈”里本地变量表中的一个,约4 个字节,相对于整个的大小来说并不是问题,弹出后会销毁。
从汇编的角度
“临时变量方案 ”
movl b, %eax ;将b从内存载入到寄存器eax(读) movl a, %edx ;将a从内存载入到寄存器edx(读) movl %eax, a ;将eax的内容存入到内存a中(写) xorl %eax, %eax ;将eax置0:设置返回值 movl %edx, b ;将edx的内容存入到内存b中(写)
内含四个内存与寄存器之间交换数据的指令,两读两写。
“异或方案”
movl b, %eax ;将b从内存载入寄存器eax(读) movl a, %ecx ;将a从内存载入寄存器ecx(读) movl %eax, %edx ;将eax的值保存到edx中(写) xorl %ecx, %edx ;ecx与edx异或 xorl %edx, %eax ;edx与eax异或 xorl %eax, %edx ;eax与edx异或 movl %eax, b ;将eax的值存入到内存b中(写) xorl %eax, %eax ;将eax置0:设置返回值 movl %edx, a ;将edx的值存入到内存a中(写)
后记
在学习中看到另一种见解:
使用异或来完成可以只限于寄存器中,不需要访存
一方面,如果编译器希望交换两个寄存器的值,它可以选择发射异或运算指令来实现(比如为了吻合 calling convention)。
另一方面,我使用目标为 RISCV 的 gcc 编译器 O2 优化的结果就比较简洁。局部变量不太多,都放在寄存器里面,不需要访存了
--------------------------------
本文属于阅读大佬文章学习实践后记录。故贴上出处【宫水三叶】,如大佬介意 可以评论留下修改意见。
6 
浙公网安备 33010602011771号