VC驿站

 找回密码
 加入驿站

QQ登录

只需一步,快速开始

搜索
查看: 2373|回复: 6

[原创] C语言循环的实现

[复制链接]
001
61_avatar_middle
最佳答案
0 
在线会员 发表于 2016-4-11 20:44:34 | 显示全部楼层 |阅读模式
在C语言中采用3中语法来实现循环,它们分别是while、for、do while,本文将分别说明这三种循环的实现,并对它们的运行效率进行比较。循环主要采用的是指令跳转的方式,循环都会用到jmp指令,跳转到之前循环体的位置。但是这三种循环有少许不同。
首先来看do while的实现:下面是简单的代码:
  1. int nCount = 0;
  2. int nMax = 10;
  3. do
  4. {
  5.     nCount++;
  6. } while (nCount < nMax);
  7. return 0;   
复制代码

下面对应的是它的汇编代码:
  1. 9:        int nCount = 0;
  2. 00401268   mov         dword ptr [ebp-4],0
  3. 10:       int nMax = 10;
  4. 0040126F   mov         dword ptr [ebp-8],0Ah
  5. 11:       do
  6. 12:       {
  7. 13:           nCount++;
  8. 00401276   mov         eax,dword ptr [ebp-4]
  9. 00401279   add         eax,1
  10. 0040127C   mov         dword ptr [ebp-4],eax
  11. 14:       } while (nCount < nMax);
  12. 0040127F   mov         ecx,dword ptr [ebp-4];exc = nCount
  13. 00401282   cmp         ecx,dword ptr [ebp-8];比较nCount 和 nMax的值
  14. 00401285   jl          main+26h (00401276);跳转到循环体中
  15. 15:       return 0;
  16. 00401287   xor         eax,eax
复制代码


在汇编代码中首先执行了一次循环体中的操作,然后判断,当条件满足时会跳转回循环体,然后再次执行,当条件不满足时会接着执行后面的语句。
这个过程可以用goto来模拟:
  1.    int nCount = 0;
  2.     int nMax = 10;
  3. __WHILE:
  4.     nCount++;
  5.     if(nCount < nMax)
  6.         goto __WHILE;
复制代码


while循环

不同于do while的先执行再比较,while采取的是先比较再循环的方式,下面是一个while的例子:
  1.     int nCount = 0;
  2.     int nMax = 10;
  3.     while (nCount < nMax)
  4.     {
  5.         nCount++;
  6.     }
复制代码

  1. 00401268   mov         dword ptr [ebp-4],0
  2. 10:       int nMax = 10;
  3. 0040126F   mov         dword ptr [ebp-8],0Ah
  4. 11:       while (nCount < nMax)
  5. 00401276   mov         eax,dword ptr [ebp-4]
  6. 00401279   cmp         eax,dword ptr [ebp-8]
  7. 0040127C   jge         main+39h (00401289)
  8. 12:       {
  9. 13:           nCount++;
  10. 0040127E   mov         ecx,dword ptr [ebp-4]
  11. 00401281   add         ecx,1
  12. 00401284   mov         dword ptr [ebp-4],ecx
  13. 14:       }
  14. 00401287   jmp         main+26h (00401276)
  15. 15:       return 0;
  16. 00401289   xor         eax,eax
复制代码


从汇编代码上可以看出,执行while循环时会有两次跳转,当条件不满足时会执行一次跳转,跳转到循环体外,而条件满足,执行完一次循环后,会再次跳转到循环体中,再次进行比较。相比于do while来说,while执行了两次跳转,效率相对较低。

for 循环

for循环是首先进行初始化操作然后进行比较,条件满足时执行循环,再将循环变量递增,最后再次比较,执行循环或者跳出。下面是for的简单例子:

  1.     int nMax = 10;
  2.     for (int i = 0; i < nMax; i++)
  3.     {
  4.         printf("%d\n", i);
  5.     }
复制代码


下面是它对应的汇编代码:

  1. 9:        int nMax = 10;
  2. 00401268   mov         dword ptr [ebp-4],0Ah
  3. 10:       for (int i = 0; i < nMax; i++)
  4. 0040126F   mov         dword ptr [ebp-8],0 ;初始化循环变量
  5. 00401276   jmp         main+31h (00401281);跳转到比较操作处
  6. 00401278   mov         eax,dword ptr [ebp-8]
  7. 0040127B   add         eax,1
  8. 0040127E   mov         dword ptr [ebp-8],eax;这三句话实现的是循环变量自增操作
  9. 00401281   mov         ecx,dword ptr [ebp-8];ecx = i
  10. 00401284   cmp         ecx,dword ptr [ebp-4];比较ecx与i
  11. 00401287   jge         main+4Ch (0040129c);跳转到循环体外
  12. 11:       {
  13. 12:           printf("%d\n", i);
  14. 00401289   mov         edx,dword ptr [ebp-8]
  15. 0040128C   push        edx
  16. 0040128D   push        offset string "%d\n" (0042e01c)
  17. 00401292   call        printf (00401540)
  18. 00401297   add         esp,8
  19. 13:       }
  20. 0040129A   jmp         main+28h (00401278);跳转到i++位置
  21. 14:       return 0;
  22. 0040129C   xor         eax,eax
复制代码


从上面的汇编代码可以看出for循环的效率最低,它经过了3次跳转,生成对应的汇编代码上,初始化操作后面紧接着是循环变量自增操作,所以首先在完成初始化后会进行一次跳转,跳转到判断,然后根据判断条件再次跳转或者接着执行循环体,最后当循环完成后会再次跳转到循环变量自增的位置,同样采用goto语句来模拟这个操作:

  
  1. int nMax = 10;
  2.     int i = 0;
  3.     goto __CMP;
  4. __ADD:
  5.     i++;
  6. __CMP:
  7.     if (i >= nMax)
  8.     {
  9.         goto __RETURN;
  10.     }

  11. __LOOP:
  12.     printf("%d\n", i);
  13.     goto __ADD;
  14. __RETURN:
  15.     return 0;
复制代码


continue语句

continue用于结束这次循环进入下一次循环,下面采用最复杂的for循环来说明continue语句,对于while和do while continue语句实现的作用都与for是一样的:
  1. int nMax = 10;
  2.     int i = 0;
  3.     for(;i < nMax; i++)
  4.     {
  5.         if (i == 6)
  6.         {
  7.             continue;
  8.         }
  9.     }
复制代码


下面是它对应的汇编代码:
  1. 00401268   mov         dword ptr [ebp-4],0Ah
  2. 10:       int i = 0;
  3. 0040126F   mov         dword ptr [ebp-8],0
  4. 11:       for(;i < nMax; i++)
  5. 00401276   jmp         main+31h (00401281)
  6. 00401278   mov         eax,dword ptr [ebp-8]
  7. 0040127B   add         eax,1
  8. 0040127E   mov         dword ptr [ebp-8],eax
  9. 00401281   mov         ecx,dword ptr [ebp-8]
  10. 00401284   cmp         ecx,dword ptr [ebp-4]
  11. 00401287   jge         main+43h (00401293)
  12. 12:       {
  13. 13:           if (i == 6)
  14. 00401289   cmp         dword ptr [ebp-8],6;
  15. 0040128D   jne         main+41h (00401291);条件不满足组跳转到循环结束处
  16. 14:           {
  17. 15:               continue;
  18. 0040128F   jmp         main+28h (00401278)
  19. 16:           }
  20. 17:       }
  21. 00401291   jmp         main+28h (00401278)
  22. 18:       return 0;
  23. 00401293   xor         eax,eax
复制代码

从上面的汇编代码可以看到,continue语句也是一个跳转语句,它会直接跳转到循环体的开始位置。对于for来说相对特殊一些(我觉得循环变量自增并不属于循环体),由于第一次进入循环时并没有执行循环变量自增,所以它会跳转到循环变量自增的位置,其他则直接到循环开始处。

评分

参与人数 2驿站币 +3 +2 热心值 +3 收起 理由
28_avatar_small sunlewuyou + 1 + 1 支持原创!
51_avatar_small Syc + 2 + 2 + 2 赞一个!

查看全部评分





上一篇:Switch 对 if 的优化
下一篇:VC++实现易语言取运行目录
51_avatar_middle
最佳答案
83 
online_admins 发表于 2016-4-12 09:28:58 | 显示全部楼层
很到位的分析,C语言结合汇编学习还真是能比较不错的理解C语言循环的实现
79_avatar_middle
最佳答案
0 
在线会员 发表于 2016-4-12 10:10:10 | 显示全部楼层
还有一种循环叫递归。。。C语言循环的实现
22_avatar_middle
最佳答案
0 
在线会员 发表于 2016-4-15 18:15:40 | 显示全部楼层
这些都是啥?
61_avatar_middle
最佳答案
0 
ico_lz  楼主| 发表于 2016-4-16 11:44:15 | 显示全部楼层
Rainy 发表于 2016-4-12 10:10
还有一种循环叫递归。。。

我觉得递归应该属于函数调用的问题,不应该属于循环
35_avatar_middle
最佳答案
0 
在线会员 发表于 2016-4-17 09:02:14 | 显示全部楼层
普通应用还没有达到这么精细差别的程度吧
01_avatar_middle
最佳答案
0 
在线会员 发表于 2016-4-29 13:46:03 | 显示全部楼层
学习。学习。。。
您需要登录后才可以回帖 登录 | 加入驿站 qq_login

本版积分规则

×【发帖 友情提示】
1、请回复有意义的内容,请勿恶意灌水;
2、纯数字、字母、表情等无意义的内容系统将自动删除;
3、若正常回复后帖子被自动删除,为系统误删的情况,请重新回复其他正常内容或等待管理员审核通过后会自动发布;
4、感谢您对VC驿站一如既往的支持,谢谢合作!

关闭

站长提醒上一条 /2 下一条

QQ|小黑屋|手机版|VC驿站 ( 辽ICP备09019393号 )|网站地图wx_jqr

GMT+8, 2021-1-21 22:45

Powered by CcTry.CoM

© 2009-2020 cctry.com

快速回复 返回顶部 返回列表