兩個變數交換的三種方法的反彙編比較

2021-09-24 13:12:33 字數 2145 閱讀 5909

先說結論:三變數交換法效率最高

起因:學了點彙編的皮毛,想看看兩變數交換的底層到底是怎麼實現的。

主體**:

//三變數交換法

int t = a;

a = b;

b = t;

//兩減一加法

a = a + b;

b = a - b;

a = a - b;

//異或法

a ^= b;

b ^= a;

a ^= b;

用vs2017進行反彙編

排版整理得

//三變數交換法

int t = a;a = b;b = t;

mov eax,a

mov t,eax

mov eax,b

mov a,eax

mov eax,t

mov b,eax

//兩減一加法

a = a + b; b = a - b; a = a - b;

mov eax,a

add eax,b

mov a,eax

mov eax,a

sub eax,b

mov b,eax

mov eax,a

sub eax,b

mov a,eax

//異或法

a ^= b;b ^

= a;a ^

= b;

mov eax,a

xor eax,b

mov a,eax

mov eax,b

xor eax,a

mov b,eax

mov eax,a

xor eax,b

mov a,eax

觀察可知,每種方法都用到了六條mov指令,但後兩種方法卻還用到了其他的指令。

這打破了我的常規認知:用的變數越少,演算法效率越高。

不,也不是完全推翻,畢竟後兩種方法確實是減少了記憶體開銷,有著更低的空間複雜度,雖然只有乙個變數那麼大。。。。。。這算是哪門子節約啊。

我原先覺得異或法最快,因為二進位制操作快,因為計算機底層就是二進位制運算。而且很多的初學者也是迷信二進位制,這種對二進位制效率的盲目認知使我寫了的a ^= b ^= a ^= b,但我從來沒有實驗過。

那麼接下來就實地測量一下:

#include

#include

#include

using

namespace std;

int a =

0,b=0;

void

fun1()

}void

fun2()

}void

fun3()

}int

main()

我的cpu是core i5-6200u,windows系統,編譯器是g++,跑出來的結果是

fun1: 2937

fun2: 5781

fun3: 5594

為了排除函式執行順序的影響,我交換了三個函式的順序又測試了兩遍

fun3: 5703

fun1: 2875

fun2: 5891

fun2: 5937

fun3: 5703

fun1: 2844

結果很明顯了,三變數交換法速度是另外兩種方法的近乎兩倍。

後記:翻了csdn,發現前人也思考過這個問題。有很多人說異或快,也有人說異或慢。但說快的一般都是拿二進位制來說事,沒有深入分析,甚至連測個速都沒有。反觀說異或慢的,深入至彙編,給出了嚴謹詳細的證明,有理有據,令人信服。

譬如下面的二位前輩:

兩個變數交換的擴充套件思考

用異或來交換兩個變數是錯誤的

感想頗多,想說的也很多,但還是老祖宗看的透徹,一言以蔽之:

交換兩個變數的三種方法

public static void main string args num1 2,num2 1前提 兩個變數相加的值不能溢位 public static void main string args num3 20,num4 10異或 1.任意乙個變數x與其自身進行異或運算,結果為0,即x x 0...

有三種方法交換兩個變數的值

int i1 20 int i2 10 int i3 i1 i1 i2 i2 i3 system.out.println i1 i1 system.out.println i2 i2 輸出結果 i1 10 i2 20 int i4 50 int i5 100 int i6 i4 i5 i5 i6 i...

交換兩個整數的三種方法

package com.zby.bubble 三種方法交換兩個整數的值 author zby public class exchange 使用乙個臨時變數交換,優點 對於其他型別同樣適用。param a param b public static void exchange1 int a,int b...