作者: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 ebp004010AD mov ebp,esp18: *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],edx19: *b=*a-*b;004010BE mov eax,dword ptr [a]004010C1 mov edx,dword ptr [b]004010C4 mov edx,dword ptr [edx]004010C6 neg edx004010C8 add edx,dword ptr [eax]004010CA mov eax,dword ptr [b]004010CD mov dword ptr [eax],edx20: *a=*a-*b;004010CF mov eax,dword ptr [a]004010D2 mov edx,dword ptr [b]004010D5 mov edx,dword ptr [edx]004010D7 neg edx004010D9 add edx,dword ptr [eax]004010DB mov eax,dword ptr [a]004010DE mov dword ptr [eax],edx21: }004010E0 leave004010E1 ret22:23: //使用临时变量24: void ExchangeValue2(int * a , int * b)25: {004010E2 push ebp004010E3 mov ebp,esp004010E5 push esi004010E6 push eax004010E7 push edi004010E8 push ecx004010E9 mov edi,ebp004010EB sub edi,4004010EE mov ecx,1004010F3 mov eax,0CCCCCCCCh004010F8 rep stos dword ptr [edi]004010FA pop ecx004010FB pop edi004010FC pop eax26: int c;27: c=*a;004010FD mov eax,dword ptr [a]00401100 mov eax,dword ptr [eax]00401102 mov dword ptr [c],eax28: *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],eax29: *b=c;0040110F mov eax,dword ptr [b]00401112 mov edx,dword ptr [c]00401115 mov dword ptr [eax],edx30: }00401117 leave00401118 ret