zoukankan      html  css  js  c++  java
  • 用汇编的眼光看C++(之循环流程) 四

    【 声明:版权所有,欢迎转载,请勿用于商业用途。  联系信箱:feixiaoxing @163.com】


        循环是我们编程中遇到的另外一项重要技术。通过反复的迭代运算,我们可以获取想要的任何结果。当然这种迭代是有基本条件的,或是以时间为条件的,或是以空间为条件的,或者是某一种外来交互作为条件的。循环的方式有很多种,但是常用的还是:while、for、do-while、goto这几种。很多公司的项目都不喜欢goto,这其中倒不是说goto不好,主要是goto的随意性太大,一旦用的不好,就会降低代码的可读性,反而影响其他人的工作效率。

        (1)do-while为什么先执行,后判断?

        老规矩,我们还是先看代码示例再说:

    1. 21:       int m = 10;  
    2. 00401638   mov         dword ptr [ebp-4],0Ah  
    3. 22:       do {  
    4. 23:           printf("%d\n", m);  
    5. 0040163F   mov         eax,dword ptr [ebp-4]  
    6. 00401642   push        eax  
    7. 00401643   push        offset string "%d\n" (0046f01c)  
    8. 00401648   call        printf (00420fb0)  
    9. 0040164D   add         esp,8  
    10. 24:           m ++;  
    11. 00401650   mov         ecx,dword ptr [ebp-4]  
    12. 00401653   add         ecx,1  
    13. 00401656   mov         dword ptr [ebp-4],ecx  
    14. 25:       }while(m < 10);  
    15. 00401659   cmp         dword ptr [ebp-4],0Ah  
    16. 0040165D   jl          process+1Fh (0040163f)  
        如果换成while呢?

    1. 21:       int m = 10;  
    2. 00401638   mov         dword ptr [ebp-4],0Ah  
    3. 22:       while(m < 20)  
    4. 0040163F   cmp         dword ptr [ebp-4],14h  
    5. 00401643   jge         process+41h (00401661)  
    6. 23:       {  
    7. 24:           printf("%d\n", m);  
    8. 00401645   mov         eax,dword ptr [ebp-4]  
    9. 00401648   push        eax  
    10. 00401649   push        offset string "%d\n" (0046f01c)  
    11. 0040164E   call        printf (00420fb0)  
    12. 00401653   add         esp,8  
    13. 25:           m ++;  
    14. 00401656   mov         ecx,dword ptr [ebp-4]  
    15. 00401659   add         ecx,1  
    16. 0040165C   mov         dword ptr [ebp-4],ecx  
    17. 26:       }  
    18. 0040165F   jmp         process+1Fh (0040163f)  
    19. 27:   }  
        其实,上面的代码表现已经很明显了。do-while的时候,模块上来先进行运算,然后再判断数据范围的大小;while就不一样,上来就进行判断,判断成功就继续运行,否则就退出循环模块,如果是for的情况呢?

    1. 21:       for(int m = 10; m < 20; m++)  
    2. 00401638   mov         dword ptr [ebp-4],0Ah  
    3. 0040163F   jmp         process+2Ah (0040164a)  
    4. 00401641   mov         eax,dword ptr [ebp-4]  
    5. 00401644   add         eax,1  
    6. 00401647   mov         dword ptr [ebp-4],eax  
    7. 0040164A   cmp         dword ptr [ebp-4],14h  
    8. 0040164E   jge         process+4Ch (0040166c)  
    9. 22:       {  
    10. 23:           printf("%d\n", m);  
    11. 00401650   mov         ecx,dword ptr [ebp-4]  
    12. 00401653   push        ecx  
    13. 00401654   push        offset string "%d\n" (0046f01c)  
    14. 00401659   call        printf (00420fc0)  
    15. 0040165E   add         esp,8  
    16. 24:           m ++;  
    17. 00401661   mov         edx,dword ptr [ebp-4]  
    18. 00401664   add         edx,1  
    19. 00401667   mov         dword ptr [ebp-4],edx  
    20. 25:       }  
    21. 0040166A   jmp         process+21h (00401641)  
        我们发现,其实for和上面的while,do-while有点小区别。在m第一次赋值的时候,并不进行加1处理,而是直接跳到地址0x40164a处运行,判断m数值和20进行判断。判断成功,则跳入循环模块,否则越过循环模块。那么,在循环处理结束后呢?也就是m++后,循环模块是怎么处理的?我们发现代码又回到了0x00401641处处理。但是这里并不是整个循环模块开始出的代码,而是对m进行自增处理。完成自增后,继续判断,下面的流程和第一次一样,不再赘述。


        (2)多重循环怎么跳出来?

        很多朋友编码的时候都有这样的一个困扰,有的时候希望在多层循环中寻找某一个条件的变量,但是在找到特定变量后,希望赶快退出循环。我们应该怎么做呢,下面是我个人的做法,仅供大家参考。

    1. int flag = 0;   
    2.        for(int m = 1; m < 20 && !flag; m++)  
    3. {  
    4.     for(int n = 1; n < 20 && !flag; n++)  
    5.     {  
    6.         for(int t = 1; t < 20 && !flag; t++)  
    7.         {  
    8.             if(/* special conditions are satisfied */)  
    9.                 flag = 1;  
    10.         }  
    11.     }  
    12. }  


        (3)while(1)是否有其他的表示方法?

    1. int flag = 0;  
    2. for(;;) {  
    3.     /* code segment */  
    4. }  
    5.   
    6. do{  
    7.     /* code segment */  
    8. }while(1);  
    9.   
    10.  loop:  
    11. {  
    12.     /* code segment */  
    13. }  
    14.   
    15. if(!flag)  
    16.     goto loop;  

    总结:

        其实,循环中还有很多的细节需要处理,你比如说:

        (1)循环的时候请务必填上程序终止的条件

        (2)循环的时候注意8位char和32和int之间的区别,务必不要死循环

        (3)字符的循环务必注意‘\0’

        (4)不要把循环、判断合二为1,给你的同事留条活路,不要以为while(*dst ++  = *src ++);这样写代码很帅

        (5)务必注意自己的返回值是你需要的那个地址,还是前一个地址,还是下一个地址

         (6)不要在for(;;)中添加额外的语句,加的越多,风险越多

        

  • 相关阅读:
    手机评測怎么看?
    【c++】简单的string类的几个基本函数
    免费软件怎样赚钱?
    【leetcode】Swap Nodes in Pairs (middle)
    【leetcode】Divide Two Integers (middle)☆
    【leetcode】4Sum(middle)
    【leetcode】Longest Common Prefix (easy)
    【leetcode】3Sum Closest(middle)
    【leetcode】Container With Most Water(middle)
    【leetcode】Palindrome Number (easy)
  • 原文地址:https://www.cnblogs.com/sier/p/5676494.html
Copyright © 2011-2022 走看看