当前位置:编程学习 > 网站相关 >>

关于最优无限循环的考证

昨天在一个论坛里看到一个帖子,是关于无限循环的选择问题,之前也看到过很多次说空for比while(1)效率高的论述,只是之前一直没有功夫去考证。
   话不多说,直入正题。
/*
 *\brief 示例一:空for  
 */ 
int main() 
{    
  for(;;)    
  {}  
  return 0; 
}
 
/* 
 *\brief 示例二:while(1)  
 */ 
int main() 
{     
  while(1) 
  {}     
  return 0; 
}
   借用曾经看到的某论坛易做图逢帖必发的一句话“不要迷信语言,要迷信编译器”,撇去我对此人的偏见,对于这句话我还是比较认同的,毕竟自己写的代码最终是由你用的编译器来编译并连接成的,语言只是你和它打交道的中介,至于最终怎么解释执行,完全是它有最终解释权。
   有点偏题,直接上编译器生成的汇编码(注,此处编译器及版本为:g++ (GCC) 4.4.6 20120305)
400554:   55                      push   %rbp   
400555:   48 89 e5              mov   %rsp,%rbp   
400558:   eb fe                  jmp    400558 <main+0x4>   
40055a:   90                      nop    
40055b:   90                      nop    
40055c:   90                      nop    
40055d:   90                      nop    
40055e:   90                      nop    
40055f:   90                      nop
   两者生成的汇编代码一致,就不多贴一份了。
   事实证明,两种无限循环写法最终运行效率一样,但是为什么这么多人说空for要比while(1)效率高呢?这其中还不乏一些很大的知名开源团队。出于科学求证的态度我又测试了老的GCC版本(g++ (GCC) 3.2.4),证明和上面大体是一样的。但是当我用VS2010和VC6.0测试时区别就出来了。
   结果如下:
for(;;) 的反汇编:  
int main()
{
00411350  push        ebp  
00411351  mov         ebp,esp  
00411353  sub         esp,0C0h  
00411359  push        ebx  
0041135A  push        esi  
0041135B  push        edi  
0041135C  lea         edi,[ebp-0C0h]  
00411362  mov         ecx,30h  
00411367  mov         eax,0CCCCCCCCh  
0041136C  rep stos    dword ptr es:[edi]  
    for(;;)
    {
    }
0041136E  jmp         main+1Eh (41136Eh)  
    return 0;
00411370  xor         eax,eax  
}
 
while(1)的反汇编: 
int main() 
00411350  push        ebp   
00411351  mov         ebp,esp   
00411353  sub         esp,0C0h   
00411359  push        ebx   
0041135A  push        esi   
0041135B  push        edi   
0041135C  lea         edi,[ebp-0C0h]   
00411362  mov         ecx,30h   
00411367  mov         eax,0CCCCCCCCh   
0041136C  rep stos    dword ptr es:[edi]       
   while(1) 
0041136E  mov         eax,1   
00411373  test        eax,eax   
00411375  je          main+29h (411379h)       
   {     
   } 
00411377  jmp         main+1Eh (41136Eh)       
   return 0; 
00411379  xor         eax,eax  
 }
   显而易见,VS平台下for(;;)生成的汇编指令少,并且不占用寄存器,没有多余的判断和跳转,比while (1)性能要好。
   其实这种平台相关的代码之前我也在一篇博文中说过(见:编译器背后的小故事),
   C++标准仅仅是一些规则,而编译器才是最终规则的实现者,对于很多细节规则并没有限定,这也要求我们尽量明确写出与编译器实现差异无关的代码,就如char的实现是按照signed还是unsigned等等,这些标准没有具体说明,各个编译器厂商自然会有各自的实现方法,很多时候我们在一个平台习惯的东西,换到另一个平台就不一定凑效,这时候就需要我们知道编译器具体实现的过程,或者只需要看一下实现的结果。
   正如那句“不存在没有bug的程序,只存在暂时未发现bug的程序”一样,程序员的世界里,“没有最好,只有更好” 也是至理名言       ---peakflys
补充:综合编程 , 其他综合 ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,