zoukankan      html  css  js  c++  java
  • C语言循环的实现

    在C语言中采用3中语法来实现循环,它们分别是while、for、do while,本文将分别说明这三种循环的实现,并对它们的运行效率进行比较。
    

    do while

    首先来看do while的实现:下面是简单的代码:
    
    int nCount = 0;
    int nMax = 10;
    do 
    {
        nCount++;
    } while (nCount < nMax);
    return 0;   

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

    9:        int nCount = 0;
    00401268   mov         dword ptr [ebp-4],0
    10:       int nMax = 10;
    0040126F   mov         dword ptr [ebp-8],0Ah
    11:       do
    12:       {
    13:           nCount++;
    00401276   mov         eax,dword ptr [ebp-4]
    00401279   add         eax,1
    0040127C   mov         dword ptr [ebp-4],eax
    14:       } while (nCount < nMax);
    0040127F   mov         ecx,dword ptr [ebp-4];exc = nCount
    00401282   cmp         ecx,dword ptr [ebp-8];比较nCount 和 nMax的值
    00401285   jl          main+26h (00401276);跳转到循环体中
    15:       return 0;
    00401287   xor         eax,eax

    在汇编代码中首先执行了一次循环体中的操作,然后判断,当条件满足时会跳转回循环体,然后再次执行,当条件不满足时会接着执行后面的语句。
    这个过程可以用goto来模拟:

        int nCount = 0;
        int nMax = 10;
    __WHILE:
        nCount++;
        if(nCount < nMax)
            goto __WHILE;

    while循环

    不同于do while的先执行再比较,while采取的是先比较再循环的方式,下面是一个while的例子:

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

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

    for 循环

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

        int nMax = 10;
        for (int i = 0; i < nMax; i++)
        {
            printf("%d
    ", i);
        }

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

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

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

        int nMax = 10;
        int i = 0;
        goto __CMP;
    __ADD:
        i++;
    __CMP:
        if (i >= nMax)
        {
            goto __RETURN;
        }
    
    __LOOP:
        printf("%d
    ", i);
        goto __ADD;
    __RETURN:
        return 0;

    continue语句

    continue用于结束这次循环进入下一次循环,下面采用最复杂的for循环来说明continue语句:
    
    int nMax = 10;
        int i = 0;
        for(;i < nMax; i++)
        {
            if (i == 6)
            {
                continue;
            }
        }

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

    00401268   mov         dword ptr [ebp-4],0Ah
    10:       int i = 0;
    0040126F   mov         dword ptr [ebp-8],0
    11:       for(;i < nMax; i++)
    00401276   jmp         main+31h (00401281)
    00401278   mov         eax,dword ptr [ebp-8]
    0040127B   add         eax,1
    0040127E   mov         dword ptr [ebp-8],eax
    00401281   mov         ecx,dword ptr [ebp-8]
    00401284   cmp         ecx,dword ptr [ebp-4]
    00401287   jge         main+43h (00401293)
    12:       {
    13:           if (i == 6)
    00401289   cmp         dword ptr [ebp-8],6;
    0040128D   jne         main+41h (00401291);条件不满足组跳转到循环结束处
    14:           {
    15:               continue;
    0040128F   jmp         main+28h (00401278)
    16:           }
    17:       }
    00401291   jmp         main+28h (00401278)
    18:       return 0;
    00401293   xor         eax,eax
    

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

  • 相关阅读:
    学习笔记4
    学习笔记3
    学习笔记2
    学习笔记1
    MySQL 随笔总结
    java1-4
    java1-3
    java1-2
    java 1-1
    Mysql 基础
  • 原文地址:https://www.cnblogs.com/lanuage/p/7725751.html
Copyright © 2011-2022 走看看