C中不使用临时变量交换两个变量的值

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操作,各种指令的执行周期也不同,所以很难判断哪种方法更好,况且对于这么一个小问题来分析它的执行效率似乎有点小题大作,我就不往下分析了。有兴趣的朋友可以继续分析一下,只是别忘了把结果告诉我哦!
评论 25
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值