免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 21276 | 回复: 20
打印 上一主题 下一主题

while与for执行效率对比 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-04-20 00:29 |只看该作者 |倒序浏览
C语言编译环境: Microsoft Visual C++ 6.0(SP6)



测试程序
  1. #include "stdio.h"

  2. void forTest()
  3. {
  4.         int num = 1234;                                        // 迭代次数
  5.         long sum = 0;                                        // 保存加法结果

  6.         for(int i=0;i<num;i++)                // 传统for循环写法
  7.         {
  8.                 sum = sum + i;                                // 计算结果
  9.         }

  10.         printf("forTest:%d\n",sum);
  11. }

  12. void whileTest()
  13. {
  14.         int num = 1234;                                        // 迭代次数
  15.         long sum = 0;                                        // 保存加法结果

  16.         while((num--)>0)
  17.         {
  18.                 sum = sum + num;                        // 计算结果
  19.         }

  20.         printf("whileTest:%d\n",sum);
  21. }


  22. void main()
  23. {
  24.         forTest();
  25.         whileTest();
  26. }
复制代码
汇编片段

whileTest()函数汇编后的指令:

--- D:\VC\ForWhile\ForWhile.cpp  ------------------------------------------------------------------------------------------
  1. 17:   void whileTest()
  2. 18:   {
  3. 0040D760   push        ebp
  4. 0040D761   mov         ebp,esp
  5. 0040D763   sub         esp,48h
  6. 0040D766   push        ebx
  7. 0040D767   push        esi
  8. 0040D768   push        edi
  9. 0040D769   lea         edi,[ebp-48h]
  10. 0040D76C   mov         ecx,12h
  11. 0040D771   mov         eax,0CCCCCCCCh
  12. 0040D776   rep stos    dword ptr [edi]
  13. 19:       int num = 1234;
  14. 0040D778   mov         dword ptr [ebp-4],4D2h
  15. 20:       long sum = 0;
  16. 0040D77F   mov         dword ptr [ebp-8],0
  17. 21:
  18. 22:       while((num--)>0)
  19. 0040D786   mov         eax,dword ptr [ebp-4]
  20. 0040D789   mov         ecx,dword ptr [ebp-4]
  21. 0040D78C   sub         ecx,1
  22. 0040D78F   mov         dword ptr [ebp-4],ecx
  23. 0040D792   test        eax,eax
  24. 0040D794   jle         whileTest+41h (0040d7a1)
  25. 23:       {
  26. 24:           sum = sum + num;
  27. 0040D796   mov         edx,dword ptr [ebp-8]
  28. 0040D799   add         edx,dword ptr [ebp-4]
  29. 0040D79C   mov         dword ptr [ebp-8],edx
  30. 25:       }
  31. 0040D79F   jmp         whileTest+26h (0040d786)
  32. 26:
  33. 27:       printf("whileTest:%d\n",sum);
  34. 0040D7A1   mov         eax,dword ptr [ebp-8]
  35. 0040D7A4   push        eax
  36. 0040D7A5   push        offset string "whileTest:%d\n" (00422fac)
  37. 0040D7AA   call        printf (0040d6e0)
  38. 0040D7AF   add         esp,8
  39. 28:   }
  40. 0040D7B2   pop         edi
  41. 0040D7B3   pop         esi
  42. 0040D7B4   pop         ebx
  43. 0040D7B5   add         esp,48h
  44. 0040D7B8   cmp         ebp,esp
  45. 0040D7BA   call        __chkesp (0040d6a0)
  46. 0040D7BF   mov         esp,ebp
  47. 0040D7C1   pop         ebp
  48. 0040D7C2   ret
复制代码
--- No source file  -------------------------------------------------------------------------------------------------------

分析:

0040D760~0040D776: 保存栈现场 总共10条指令

0040D778: 迭代次数 总共1条指令

0040D77F: 保存加法结果 总共1条指令

0040D786~0040D79F: while循环 总共10条指令

0040D7A1~0040D7AF: 打印结果 总共5条指令

0040D7B2~0040D7C2: 恢复栈现场 总共9条指令

合计: 36条指令



forTest()函数汇编后的指令:

--- D:\VC\ForWhile\ForWhile.cpp  ------------------------------------------------------------------------------------------
  1. 4:    void forTest()
  2. 5:    {
  3. 0040D3F0   push        ebp
  4. 0040D3F1   mov         ebp,esp
  5. 0040D3F3   sub         esp,4Ch
  6. 0040D3F6   push        ebx
  7. 0040D3F7   push        esi
  8. 0040D3F8   push        edi
  9. 0040D3F9   lea         edi,[ebp-4Ch]
  10. 0040D3FC   mov         ecx,13h
  11. 0040D401   mov         eax,0CCCCCCCCh
  12. 0040D406   rep stos    dword ptr [edi]
  13. 6:        int num = 1234;
  14. 0040D408   mov         dword ptr [ebp-4],4D2h
  15. 7:        long sum = 0;
  16. 0040D40F   mov         dword ptr [ebp-8],0
  17. 8:
  18. 9:        for(int i=0;i<num;i++)
  19. 0040D416   mov         dword ptr [ebp-0Ch],0
  20. 0040D41D   jmp         forTest+38h (0040d428)
  21. 0040D41F   mov         eax,dword ptr [ebp-0Ch]
  22. 0040D422   add         eax,1
  23. 0040D425   mov         dword ptr [ebp-0Ch],eax
  24. 0040D428   mov         ecx,dword ptr [ebp-0Ch]
  25. 0040D42B   cmp         ecx,dword ptr [ebp-4]
  26. 0040D42E   jge         forTest+4Bh (0040d43b)
  27. 10:       {
  28. 11:           sum = sum + i;
  29. 0040D430   mov         edx,dword ptr [ebp-8]
  30. 0040D433   add         edx,dword ptr [ebp-0Ch]
  31. 0040D436   mov         dword ptr [ebp-8],edx
  32. 12:       }
  33. 0040D439   jmp         forTest+2Fh (0040d41f)
  34. 13:
  35. 14:       printf("forTest:%d\n",sum);
  36. 0040D43B   mov         eax,dword ptr [ebp-8]
  37. 0040D43E   push        eax
  38. 0040D43F   push        offset string "forTest:%l\n" (00422e80)
  39. 0040D444   call        printf (0040d6e0)
  40. 0040D449   add         esp,8
  41. 15:   }
  42. 0040D44C   pop         edi
  43. 0040D44D   pop         esi
  44. 0040D44E   pop         ebx
  45. 0040D44F   add         esp,4Ch
  46. 0040D452   cmp         ebp,esp
  47. 0040D454   call        __chkesp (0040d6a0)
  48. 0040D459   mov         esp,ebp
  49. 0040D45B   pop         ebp
  50. 0040D45C   ret
复制代码

论坛徽章:
0
2 [报告]
发表于 2011-04-20 00:30 |只看该作者
--- No source file  -------------------------------------------------------------------------------------------------------

分析:

0040D3F0~0040D406: 保存栈现场 总共10条指令

0040D408: 迭代次数 总共1条指令

0040D40F: 保存加法结果 总共1条指令

0040D416~0040D439: for循环 总共12条指令

0040D43B~0040D449: 打印结果 总共5条指令

0040D44C~0040D45C: 恢复栈现场 总共9条指令

合计: 38条指令



程序中二个方法语句区别在于一个是for循环,一个是while循环.

对应于,查看到上述二段汇编指令段while循环比for循环少了二条指令.



程序中for循环用的是传统写法,做下更改将for(int i=0;i<num;i++)改为for(;(num--)>0,其汇编指令为:

--- D:\VC\ForWhile\ForWhile.cpp  ------------------------------------------------------------------------------------------
  1. 4:    void forTest()
  2. 5:    {
  3. 0040D3F0   push        ebp
  4. 0040D3F1   mov         ebp,esp
  5. 0040D3F3   sub         esp,48h
  6. 0040D3F6   push        ebx
  7. 0040D3F7   push        esi
  8. 0040D3F8   push        edi
  9. 0040D3F9   lea         edi,[ebp-48h]
  10. 0040D3FC   mov         ecx,12h
  11. 0040D401   mov         eax,0CCCCCCCCh
  12. 0040D406   rep stos    dword ptr [edi]
  13. 6:        int num = 1234;
  14. 0040D408   mov         dword ptr [ebp-4],4D2h
  15. 7:        long sum = 0;
  16. 0040D40F   mov         dword ptr [ebp-8],0
  17. 8:
  18. 9:        for(;(num--)>0;)
  19. 0040D416   mov         eax,dword ptr [ebp-4]
  20. 0040D419   mov         ecx,dword ptr [ebp-4]
  21. 0040D41C   sub         ecx,1
  22. 0040D41F   mov         dword ptr [ebp-4],ecx
  23. 0040D422   test        eax,eax
  24. 0040D424   jle         forTest+41h (0040d431)
  25. 10:       {
  26. 11:           sum = sum + num;
  27. 0040D426   mov         edx,dword ptr [ebp-8]
  28. 0040D429   add         edx,dword ptr [ebp-4]
  29. 0040D42C   mov         dword ptr [ebp-8],edx
  30. 12:       }
  31. 0040D42F   jmp         forTest+26h (0040d416)
  32. 13:
  33. 14:       printf("forTest:%d\n",sum);
  34. 0040D431   mov         eax,dword ptr [ebp-8]
  35. 0040D434   push        eax
  36. 0040D435   push        offset string "forTest:%l\n" (00422e80)
  37. 0040D43A   call        printf (0040d6e0)
  38. 0040D43F   add         esp,8
  39. 15:   }
  40. 0040D442   pop         edi
  41. 0040D443   pop         esi
  42. 0040D444   pop         ebx
  43. 0040D445   add         esp,48h
  44. 0040D448   cmp         ebp,esp
  45. 0040D44A   call        __chkesp (0040d6a0)
  46. 0040D44F   mov         esp,ebp
  47. 0040D451   pop         ebp
  48. 0040D452   ret
复制代码
  1. 4:    void forTest()
  2. 5:    {
  3. 0040D3F0   push        ebp
  4. 0040D3F1   mov         ebp,esp
  5. 0040D3F3   sub         esp,48h
  6. 0040D3F6   push        ebx
  7. 0040D3F7   push        esi
  8. 0040D3F8   push        edi
  9. 0040D3F9   lea         edi,[ebp-48h]
  10. 0040D3FC   mov         ecx,12h
  11. 0040D401   mov         eax,0CCCCCCCCh
  12. 0040D406   rep stos    dword ptr [edi]
  13. 6:        int num = 1234;
  14. 0040D408   mov         dword ptr [ebp-4],4D2h
  15. 7:        long sum = 0;
  16. 0040D40F   mov         dword ptr [ebp-8],0
  17. 8:
  18. 9:        for(;(num--)>0;)
  19. 0040D416   mov         eax,dword ptr [ebp-4]
  20. 0040D419   mov         ecx,dword ptr [ebp-4]
  21. 0040D41C   sub         ecx,1
  22. 0040D41F   mov         dword ptr [ebp-4],ecx
  23. 0040D422   test        eax,eax
  24. 0040D424   jle         forTest+41h (0040d431)
  25. 10:       {
  26. 11:           sum = sum + num;
  27. 0040D426   mov         edx,dword ptr [ebp-8]
  28. 0040D429   add         edx,dword ptr [ebp-4]
  29. 0040D42C   mov         dword ptr [ebp-8],edx
  30. 12:       }
  31. 0040D42F   jmp         forTest+26h (0040d416)
  32. 13:
  33. 14:       printf("forTest:%d\n",sum);
  34. 0040D431   mov         eax,dword ptr [ebp-8]
  35. 0040D434   push        eax
  36. 0040D435   push        offset string "forTest:%l\n" (00422e80)
  37. 0040D43A   call        printf (0040d6e0)
  38. 0040D43F   add         esp,8
  39. 15:   }
  40. 0040D442   pop         edi
  41. 0040D443   pop         esi
  42. 0040D444   pop         ebx
  43. 0040D445   add         esp,48h
  44. 0040D448   cmp         ebp,esp
  45. 0040D44A   call        __chkesp (0040d6a0)
  46. 0040D44F   mov         esp,ebp
  47. 0040D451   pop         ebp
  48. 0040D452   ret
复制代码
--- No source file  -------------------------------------------------------------------------------------------------------

0040D3F0~0040D406: 保存栈现场 总共10条指令

0040D408: 迭代次数 总共1条指令

0040D40F: 保存加法结果 总共1条指令

0040D416~0040D42F: for循环 总共10条指令

0040D431~0040D43F: 打印结果 总共5条指令

0040D442~0040D452: 恢复栈现场 总共9条指令

合计: 36条指令



由此可见,for循环习惯写法for(int i=0;i<num;i++)执行效率低于for(;(num--)>0写法,而for(;(num--)>0写法执行效率与while((num--)>0)相同.




因此,一棒子打死说for循环执行效率比while循环慢是不对的.

论坛徽章:
0
3 [报告]
发表于 2011-04-20 04:06 |只看该作者
分析的不错

论坛徽章:
2
天蝎座
日期:2014-03-28 10:18:052015年亚洲杯之乌兹别克斯坦
日期:2015-02-10 11:32:25
4 [报告]
发表于 2011-04-20 09:17 |只看该作者
用汇编来说明问题,比较有说服力啊{:3_189:}

论坛徽章:
0
5 [报告]
发表于 2011-04-20 09:31 |只看该作者
补充一下哈,一般来说,do..while循环要比for,while循环的效率要高,这点可以从你做过的汇编分析中看出,而且在深入理解计算机一书的第三章3.6.5节中的讲述也可以看出在对上述循环语句进行汇编时,会先将for,while转换为do..while。

论坛徽章:
324
射手座
日期:2013-08-23 12:04:38射手座
日期:2013-08-23 16:18:12未羊
日期:2013-08-30 14:33:15水瓶座
日期:2013-09-02 16:44:31摩羯座
日期:2013-09-25 09:33:52双子座
日期:2013-09-26 12:21:10金牛座
日期:2013-10-14 09:08:49申猴
日期:2013-10-16 13:09:43子鼠
日期:2013-10-17 23:23:19射手座
日期:2013-10-18 13:00:27金牛座
日期:2013-10-18 15:47:57午马
日期:2013-10-18 21:43:38
6 [报告]
发表于 2011-04-20 09:37 |只看该作者
for 比while复杂也更灵活

论坛徽章:
0
7 [报告]
发表于 2011-04-20 09:43 |只看该作者
LZ有成为程序员教科书的潜力

论坛徽章:
0
8 [报告]
发表于 2011-04-20 09:45 |只看该作者
研究研究还是不错的,不过实际情况,使用哪种循环对效率没啥大的影响

关键还是循环体的优化啊。。

论坛徽章:
0
9 [报告]
发表于 2011-04-20 14:36 |只看该作者
mark,学习了.

论坛徽章:
1
2015年迎新春徽章
日期:2015-03-04 09:56:11
10 [报告]
发表于 2011-04-20 15:00 |只看该作者
這個不是關鍵慢的地方,只需要關鍵點優化就好。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP