C中不使用临时变量交换两个变量的值
作者:yxin1322
blog:
http://blog.csdn.net/yxin1322
转载请注明出处
前两天同学去面试,碰到一道C算法题,要求不使用额外的临时变量而交换两个变量的值,这个问题以前曾经在qq群里和人讨论过,所以有点印象,具体实现同样是三句赋值语句,只是巧妙的运用了和与差的运算来达到交换的目的。
1 #include <stdio.h> 2 3 void ExchangeValue1(int * a,int * b); 4 void ExchangeValue2(int * a,int * b); 5 6 main() 7 { 8 int a=1; 9 int b=2; 10 printf("a=%d,b=%d/n",a,b); 11 ExchangeValue1(&a,&b); 12 printf("a=%d,b=%d/n",a,b); 13 } 14 15 //不使用临时变量 16 void ExchangeValue1(int * a,int * b) 17 { 18 *a=*a+*b; 19 *b=*a-*b; 20 *a=*a-*b; 21 } 22 23 //使用临时变量 24 void ExchangeValue2(int * a , int * b) 25 { 26 int c; 27 c=*a; 28 *a=*b; 29 *b=c; 30 }
ExchangeValue2是传统的交换方法,用到了一个临时变量。ExchangeValue1没有用到临时变量,只是通过两变量间的加减运算就完成了变量值的“交换”,这种方法看起来还是很新颖的,但它只适合于交换支持加减运算的值类型,如果是两个结构体变量或类对象就没办法了,只能乖乖地用临时变量来中转。那么哪种方式要高效一点呢?看以下反汇编代码:
15: //不使用临时变量
16: void ExchangeValue1(int * a, int * b)
17: {
004010AC push ebp
004010AD mov ebp,esp
18: *a=*a+*b;
004010AF mov eax,dword ptr [a]
004010B2 mov edx,dword ptr [b]
004010B5 mov edx,dword ptr [edx]
004010B7 add edx,dword ptr [eax]
004010B9 mov eax,dword ptr [a]
004010BC mov dword ptr [eax],edx
19: *b=*a-*b;
004010BE mov eax,dword ptr [a]
004010C1 mov edx,dword ptr [b]
004010C4 mov edx,dword ptr [edx]
004010C6 neg edx
004010C8 add edx,dword ptr [eax]
004010CA mov eax,dword ptr [b]
004010CD mov dword ptr [eax],edx
20: *a=*a-*b;
004010CF mov eax,dword ptr [a]
004010D2 mov edx,dword ptr [b]
004010D5 mov edx,dword ptr [edx]
004010D7 neg edx
004010D9 add edx,dword ptr [eax]
004010DB mov eax,dword ptr [a]
004010DE mov dword ptr [eax],edx
21: }
004010E0 leave
004010E1 ret
22:
23: //使用临时变量
24: void ExchangeValue2(int * a , int * b)
25: {
004010E2 push ebp
004010E3 mov ebp,esp
004010E5 push esi
004010E6 push eax
004010E7 push edi
004010E8 push ecx
004010E9 mov edi,ebp
004010EB sub edi,4
004010EE mov ecx,1
004010F3 mov eax,0CCCCCCCCh
004010F8 rep stos dword ptr [edi]
004010FA pop ecx
004010FB pop edi
004010FC pop eax
26: int c;
27: c=*a;
004010FD mov eax,dword ptr [a]
00401100 mov eax,dword ptr [eax]
00401102 mov dword ptr [c],eax
28: *a=*b;
00401105 mov eax,dword ptr [b]
00401108 mov edx,dword ptr [a]
0040110B mov eax,dword ptr [eax]
0040110D mov dword ptr [edx],eax
29: *b=c;
0040110F mov eax,dword ptr [b]
00401112 mov edx,dword ptr [c]
00401115 mov dword ptr [eax],edx
30: }
00401117 leave
00401118 ret
以上是VC的反汇编代码,可以看出来ExchangeValue1被译成了24条汇编代码,而ExchangeValue2被译成了26条汇编代码,从代码条数上来看两种方法差不多。不过这里的代码是VC在debug模式下生成的,没有经过优化,加上ExchangeValue1有多次ADD操作,而ExchangeValue2有多次push、pop和stos操作,各种指令的执行周期也不同,所以很难判断哪种方法更好,况且对于这么一个小问题来分析它的执行效率似乎有点小题大作,我就不往下分析了。有兴趣的朋友可以继续分析一下,只是别忘了把结果告诉我哦!