消除循环的低效率

例1:

   void test1(结构体 v)
   {
     int i;
     for(i=0;i<=getLength(v);i++)
     {
       //执行代码 
     }
   }

//在常见的代码中,我们看见这种写法,会造成每次for循环都会进行getLength操作来获取长度,所以在程序中,我们通常会进行一个改进版本,如下所示:

  void test2(结构体 v)
  {
    int i;
    int j =getLength(v);
    for(i=0;i< j;j++)
     {
       //执行代码
     }
   }

这是一种很常见的优化,称之为 “代码移动”。这类优化包括识别出要执行多次,但计算结果不会发生变化的计算,因而我们可以将计算移动到代码前面,这样,就不会被多次求值。
优化编译器会试着进行代码移动,但是编译器一般很少进行移动,因为编译器担心这样移动会带来一些副作用。


例2 代码移动分析2:

  //大写字母转小写字母
  //转换小写方式1
  void zhuanhuan1(char *s){
    int i;
    for(i =0 ;i< strlen(s);i++)
    {
     if(s[i] >='A' && s[i] <='Z')
      {
        s[i] -= ('A'-'a');
      }
   }
  } 
  //转换小写方式2
  void zhuanhuan2(char *s){
     int i;
     int len = strlen(s);
     for(i =0;i< len;i++)
      {
        if(s[i] >='A' && s[i] <='Z')
         {
           s[i] -= ('A'-'a');
         }
      }
   } 
  
 //获取长度
  size_t strlen(char *s)
   {
     int length =0;
      while (*s !=0)
      {
        s++;
        length ++;
      }
      return length;
   }
 

通过测试我们发现,当我们输入260000个字符串进行转换时,zhuanhuan1需要3分钟才能进行转换完毕;
而zhuanhuan2只需要0.03秒就可以转换完毕。

从以上两个示例我们可以看出,一个小小的代码移动就可以减少程序的执行次数,使程序得到飞一般的提速,所以我们在平常的代码中,要尽量避免类似问题的发生,使我们的程序更高效。