2 Fork me on GitHub 6

交换两个数的一种方法:使用异或

开始

直接切入正题,一般不有特殊要求的时候,会通过借助一个临时变量的方法来实现。

而有些解决方案里是这样的

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 优化的结果就比较简洁。局部变量不太多,都放在寄存器里面,不需要访存了 

--------------------------------

本文属于阅读大佬文章学习实践后记录。故贴上出处【宫水三叶】,如大佬介意 可以评论留下修改意见。

posted @ 2021-04-06 13:02  linzMYN  阅读(391)  评论(0)    收藏  举报
-------