在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\n", 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\n", i);
00401289 mov edx,dword ptr [ebp-8]
0040128C push edx
0040128D push offset string "%d\n" (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\n", 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来说相对特殊一些(我觉得循环变量自增并不属于循环体),由于第一次进入循环时并没有执行循环变量自增,所以它会跳转到循环变量自增的位置,其他则直接到循环开始处。

C语言循环的实现的更多相关文章

  1. Go语言循环判断的使用~

    Go 语言条件语句 条件语句需要开发者通过指定一个或多个条件,并通过测试条件是否为 true 来决定是否执行指定语句,并在条件为 false 的情况在执行另外的语句. 下图展示了程序语言中条件语句的结 ...

  2. R语言 循环

    R语言循环 可能有一种情况,当你需要执行一段代码几次. 通常,顺序执行语句. 首先执行函数中的第一个语句,然后执行第二个语句,依此类推. 编程语言提供允许更复杂的执行路径的各种控制结构. 循环语句允许 ...

  3. C语言-循环结构及break、continue

    循环结构 --1-- 结构循环 1.1 while循环 1.2 do…while循环 1.3 for循环 --2-- break和continue 2.1 break关键字 2.2 continue关 ...

  4. go语言循环语句 for

    Go语言中的循环语句只支持for关键字,而不支持while和do-while结构. sum := 0 for i := 0; i < 10; i++ { sum += i } 无限循环的写法: ...

  5. C语言循环的嵌套

    注:参考网络资源拟制,如雷同请见谅循环的嵌套:一个循环体语句中又包含另一个循环语句,称为循环嵌套.嵌套注意事项:1.使用循环嵌套时,内层循环和外层循环的循环控制变量不能相同.2.循环嵌套结构的书写,最 ...

  6. 08-C语言循环

    目录: 一.for循环 二.break,continue 三.循环嵌套 四.while 五.do while 六.三个循环的对比 七.空语句 回到顶部 一.for循环 标识每次循环,循环终止条件,循环 ...

  7. Go 语言循环语句

    在不少实际问题中有许多具有规律性的重复操作,因此在程序中就需要重复执行某些语句. 以下为大多编程语言循环程序的流程图: Go 语言提供了以下几种类型循环处理语句: 循环类型 描述 for 循环 重复执 ...

  8. c语言循环案例

    do while #include <stdio.h> #include <stdlib.h> int main() { int a = 1,b = 10; do { b -= ...

  9. GO语言学习(十一)Go 语言循环语句

    Go 语言提供了以下几种类型循环处理语句: 循环类型 描述 for 循环 重复执行语句块 循环嵌套 在 for 循环中嵌套一个或多个 for 循环 语法 Go语言的For循环有3中形式,只有其中的一种 ...

随机推荐

  1. php之str_replace具体解释

    str_replace (PHP 4, PHP 5) str_replace - Replace all occurrences of the search string with the repla ...

  2. POJ 3928 &amp; hdu 2492 &amp; Uva1428 PingPong 【树状数组】

    Ping pong                                                   Time Limit: 2000/1000 MS (Java/Others)   ...

  3. Node.js开发Web后台服务

    一.简介 Node.js 是一个基于Google Chrome V8 引擎的 JavaScript 运行环境.Node.js 使用了一个事件驱动.非阻塞式 I/O 的模型,使其轻量又高效.Node.j ...

  4. 【quickhybrid】H5和原生的职责划分

    前言 在JSBridge实现后,前端网页与原生的交互已经通了,接下来就要开始规划API,明确需要提供哪一些功能来供前端调用. 但是在这之前,还有一点重要工作需要做: 明确H5与Native的职责划分, ...

  5. 微信小程序——轮播图实现

    小程序的轮播图,也就是他其中的一个控件可以算是直接上代码: 这是WXML 页面 代码: <view class='carousel_div'> <swiper class=" ...

  6. 原生js版分页插件

    之前我在自己的博客里发表了一篇用angularJs自定义指令实现的分页插件,今天简单改造了一下,改成了原生JavaScript版本的分页插件,可以自定义一些简单配置,特此记录下来.如有不足之处,欢迎指 ...

  7. [.Net跨平台]部署DTCMS到Jexus遇到的问题及解决思路--验证码

    上一篇博客我们已经基本完成了部署工作,目前发现了验证码出现500错误,分析其代码,我们可以看到验证码使用的是System.Drawing命名空间下的类库, GDI+ 位图,这个在肯定是平台相关的,所以 ...

  8. margin相关

    1.图片与文字对齐问题 如果图片和文字差不多大时,使用兼容性强的margin负值方法. 方法:img{margin:0 3px -3px 0;} 2.div嵌套后margin出现失效(转移)问题 原因 ...

  9. 【java】HashMap、Map、Set、HashMap.put()、HashMap.keySet()、HashMap.entrySet()、Map.Entry内部类

    package com.tn.hashMap; public class Student { private String id; private String name; public Studen ...

  10. JDK动态代理[1]----代理模式实现方式的概要介绍

    日常工作中经常会接触到代理模式,但一直没有对其进行深究.代理模式一直就像一团迷雾一样存在我心里,什么是代理模式?为什么要使用代理?代理模式有哪些实现?它的底层机制是怎样的?这些问题促使着我迫切想要揭开 ...