论坛首页 编程语言技术论坛

【C语言】while与for执行效率对比

浏览 18394 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2011-04-17   最后修改:2011-04-18
C

 

 

【C语言】while与for执行效率对比

 

C语言编译环境: Microsoft Visual C++ 6.0(SP6)

 

测试程序

 

 

#include "stdio.h"

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

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

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

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

	while((num--)>0)
	{
		sum = sum + num;			// 计算结果
	}

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


void main()
{
	forTest();
	whileTest();
}
 

 

汇编片段

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

--- D:\VC\ForWhile\ForWhile.cpp  ------------------------------------------------------------------------------------------

 

17:   void whileTest()
18:   {
0040D760   push        ebp
0040D761   mov         ebp,esp
0040D763   sub         esp,48h
0040D766   push        ebx
0040D767   push        esi
0040D768   push        edi
0040D769   lea         edi,[ebp-48h]
0040D76C   mov         ecx,12h
0040D771   mov         eax,0CCCCCCCCh
0040D776   rep stos    dword ptr [edi]
19:       int num = 1234;
0040D778   mov         dword ptr [ebp-4],4D2h
20:       long sum = 0;
0040D77F   mov         dword ptr [ebp-8],0
21:
22:       while((num--)>0)
0040D786   mov         eax,dword ptr [ebp-4]
0040D789   mov         ecx,dword ptr [ebp-4]
0040D78C   sub         ecx,1
0040D78F   mov         dword ptr [ebp-4],ecx
0040D792   test        eax,eax
0040D794   jle         whileTest+41h (0040d7a1)
23:       {
24:           sum = sum + num;
0040D796   mov         edx,dword ptr [ebp-8]
0040D799   add         edx,dword ptr [ebp-4]
0040D79C   mov         dword ptr [ebp-8],edx
25:       }
0040D79F   jmp         whileTest+26h (0040d786)
26:
27:       printf("whileTest:%d\n",sum);
0040D7A1   mov         eax,dword ptr [ebp-8]
0040D7A4   push        eax
0040D7A5   push        offset string "whileTest:%d\n" (00422fac)
0040D7AA   call        printf (0040d6e0)
0040D7AF   add         esp,8
28:   }
0040D7B2   pop         edi
0040D7B3   pop         esi
0040D7B4   pop         ebx
0040D7B5   add         esp,48h
0040D7B8   cmp         ebp,esp
0040D7BA   call        __chkesp (0040d6a0)
0040D7BF   mov         esp,ebp
0040D7C1   pop         ebp
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  ------------------------------------------------------------------------------------------

 

4:    void forTest()
5:    {
0040D3F0   push        ebp
0040D3F1   mov         ebp,esp
0040D3F3   sub         esp,4Ch
0040D3F6   push        ebx
0040D3F7   push        esi
0040D3F8   push        edi
0040D3F9   lea         edi,[ebp-4Ch]
0040D3FC   mov         ecx,13h
0040D401   mov         eax,0CCCCCCCCh
0040D406   rep stos    dword ptr [edi]
6:        int num = 1234;
0040D408   mov         dword ptr [ebp-4],4D2h
7:        long sum = 0;
0040D40F   mov         dword ptr [ebp-8],0
8:
9:        for(int i=0;i<num;i++)
0040D416   mov         dword ptr [ebp-0Ch],0
0040D41D   jmp         forTest+38h (0040d428)
0040D41F   mov         eax,dword ptr [ebp-0Ch]
0040D422   add         eax,1
0040D425   mov         dword ptr [ebp-0Ch],eax
0040D428   mov         ecx,dword ptr [ebp-0Ch]
0040D42B   cmp         ecx,dword ptr [ebp-4]
0040D42E   jge         forTest+4Bh (0040d43b)
10:       {
11:           sum = sum + i;
0040D430   mov         edx,dword ptr [ebp-8]
0040D433   add         edx,dword ptr [ebp-0Ch]
0040D436   mov         dword ptr [ebp-8],edx
12:       }
0040D439   jmp         forTest+2Fh (0040d41f)
13:
14:       printf("forTest:%d\n",sum);
0040D43B   mov         eax,dword ptr [ebp-8]
0040D43E   push        eax
0040D43F   push        offset string "forTest:%l\n" (00422e80)
0040D444   call        printf (0040d6e0)
0040D449   add         esp,8
15:   }
0040D44C   pop         edi
0040D44D   pop         esi
0040D44E   pop         ebx
0040D44F   add         esp,4Ch
0040D452   cmp         ebp,esp
0040D454   call        __chkesp (0040d6a0)
0040D459   mov         esp,ebp
0040D45B   pop         ebp
0040D45C   ret
 

--- 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  ------------------------------------------------------------------------------------------

 

4:    void forTest()
5:    {
0040D3F0   push        ebp
0040D3F1   mov         ebp,esp
0040D3F3   sub         esp,48h
0040D3F6   push        ebx
0040D3F7   push        esi
0040D3F8   push        edi
0040D3F9   lea         edi,[ebp-48h]
0040D3FC   mov         ecx,12h
0040D401   mov         eax,0CCCCCCCCh
0040D406   rep stos    dword ptr [edi]
6:        int num = 1234;
0040D408   mov         dword ptr [ebp-4],4D2h
7:        long sum = 0;
0040D40F   mov         dword ptr [ebp-8],0
8:
9:        for(;(num--)>0;)
0040D416   mov         eax,dword ptr [ebp-4]
0040D419   mov         ecx,dword ptr [ebp-4]
0040D41C   sub         ecx,1
0040D41F   mov         dword ptr [ebp-4],ecx
0040D422   test        eax,eax
0040D424   jle         forTest+41h (0040d431)
10:       {
11:           sum = sum + num;
0040D426   mov         edx,dword ptr [ebp-8]
0040D429   add         edx,dword ptr [ebp-4]
0040D42C   mov         dword ptr [ebp-8],edx
12:       }
0040D42F   jmp         forTest+26h (0040d416)
13:
14:       printf("forTest:%d\n",sum);
0040D431   mov         eax,dword ptr [ebp-8]
0040D434   push        eax
0040D435   push        offset string "forTest:%l\n" (00422e80)
0040D43A   call        printf (0040d6e0)
0040D43F   add         esp,8
15:   }
0040D442   pop         edi
0040D443   pop         esi
0040D444   pop         ebx
0040D445   add         esp,48h
0040D448   cmp         ebp,esp
0040D44A   call        __chkesp (0040d6a0)
0040D44F   mov         esp,ebp
0040D451   pop         ebp
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循环慢是不对的.


【Java语言】while与for执行效率对比: 经查看class文件反编译指令发现,Java中执行for循环与执行while循环所需的指令数是一样的,二者执行效率相同.

   发表时间:2011-04-18  
必须一样啊,在java中
0 请登录后投票
   发表时间:2011-04-18  
cectsky 写道
必须一样啊,在java中

兄台为何如此肯定.
给讲讲呗.
0 请登录后投票
   发表时间:2011-04-23   最后修改:2011-04-23

 

 写道
public static int testFor(){
int i;
int sum = 0;
for (i = 0;i < 100;i++){
sum = sum + i;
}
return sum;
}
public static int testWhile(){
int i;
int sum = 0;
i = 0;
while ( i < 100){
sum = sum + i;
i ++;
}
return sum;
}

字节码指令为:

 

public static int testFor();
  Code:
   0:	iconst_0
   1:	istore_1
   2:	iconst_0
   3:	istore_0
   4:	goto	14
   7:	iload_1
   8:	iload_0
   9:	iadd
   10:	istore_1
   11:	iinc	0, 1
   14:	iload_0
   15:	bipush	100
   17:	if_icmplt	7
   20:	iload_1
   21:	ireturn

public static int testWhile();
  Code:
   0:	iconst_0
   1:	istore_1
   2:	iconst_0
   3:	istore_0
   4:	goto	14
   7:	iload_1
   8:	iload_0
   9:	iadd
   10:	istore_1
   11:	iinc	0, 1
   14:	iload_0
   15:	bipush	100
   17:	if_icmplt	7
   20:	iload_1
   21:	ireturn

 完全一样

0 请登录后投票
   发表时间:2011-04-23  
chenqiangjsj 写道

 

 写道
public static int testFor(){
int i;
int sum = 0;
for (i = 0;i < 100;i++){
sum = sum + i;
}
return sum;
}
public static int testWhile(){
int i;
int sum = 0;
i = 0;
while ( i < 100){
sum = sum + i;
i ++;
}
return sum;
}

字节码指令为:

 

public static int testFor();
  Code:
   0:	iconst_0
   1:	istore_1
   2:	iconst_0
   3:	istore_0
   4:	goto	14
   7:	iload_1
   8:	iload_0
   9:	iadd
   10:	istore_1
   11:	iinc	0, 1
   14:	iload_0
   15:	bipush	100
   17:	if_icmplt	7
   20:	iload_1
   21:	ireturn

public static int testWhile();
  Code:
   0:	iconst_0
   1:	istore_1
   2:	iconst_0
   3:	istore_0
   4:	goto	14
   7:	iload_1
   8:	iload_0
   9:	iadd
   10:	istore_1
   11:	iinc	0, 1
   14:	iload_0
   15:	bipush	100
   17:	if_icmplt	7
   20:	iload_1
   21:	ireturn

 完全一样

也是通过字节码得出来的结果呀.

我还以为有什么其他的理论呢.

不错~~

0 请登录后投票
   发表时间:2011-04-23  
迷茫,标题指明是c语言,为什么后面变成了java的讨论了??
0 请登录后投票
   发表时间:2011-04-23  
skzr.org 写道
迷茫,标题指明是c语言,为什么后面变成了java的讨论了??

因为之前写了一篇【Java语言】while与for执行效率对比,然后想看看C里面的情况,就有了这篇.
后面的只是附加之笔.
见谅,我们可以继续这个话题.
不知道分析的是否全面....
0 请登录后投票
   发表时间:2011-04-26  
这论坛都叫javaeye 能不说java吗
0 请登录后投票
   发表时间:2011-04-26  
pywepe 写道
这论坛都叫javaeye 能不说java吗

版块也没必要区分太细.
0 请登录后投票
   发表时间:2011-04-28  
如果你理解迪米特法则(Low Of Demeter,LoD),或许你不会选择for
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics