zoukankan      html  css  js  c++  java
  • 指针访问与数组访问的效率分析

    出处:http://blog.csdn.net/pony_maggie/article/details/6748662

    很多人都知道指针访问比数组访问效率高, 但很少人明白其中的原理, 这篇文章从汇编级别上分析一下原因.


    我用一个"reverse"函数来作为例子, 分别用指针和数组的形式来实现这个函数.

    //指针访问
    void reverse(char *pStr,int nLen)
    {
     char *pStart=pStr;//指向字符串开始
     char *pEnd=pStr+nLen-1;//指向字符串结尾
     char chTmp;
     
     while(pEnd > pStart)
     { 
      chTmp = *pStart;
      *pStart = *pEnd;
      *pEnd = chTmp;
      
      pStart++;
      pEnd--;
     }
    }

    上面的函数在vc6下的反汇编代码,我加了一些注释方便理解

    19:   void reverse(char *pStr,int nLen)
    20:   {
    00401070   push        ebp
    00401071   mov         ebp,esp
    00401073   sub         esp,4Ch
    00401076   push        ebx
    00401077   push        esi
    00401078   push        edi
    00401079   lea         edi,[ebp-4Ch]
    0040107C   mov         ecx,13h
    00401081   mov         eax,0CCCCCCCCh
    00401086   rep stos    dword ptr [edi]//调用子函数时进堆栈保存信息. 
    
    00401088   mov         eax,dword ptr [ebp+8]
    0040108B   mov         dword ptr [ebp-4],eax//char *pStart=pStr;
    
    0040108E   mov         ecx,dword ptr [ebp+0Ch]
    00401091   mov         edx,dword ptr [ebp+8]
    00401094   lea         eax,[edx+ecx-1]
    00401098   mov         dword ptr [ebp-8],eax//char *pEnd=pStr+nLen-1;
       
    0040109B   mov         ecx,dword ptr [ebp-8]
    0040109E   cmp         ecx,dword ptr [ebp-4]//while(pEnd > pStart)
    004010A1   jbe         reverse+61h (004010d1)
          
    004010A3   mov         edx,dword ptr [ebp-4]//chTmp = *pStart;
    004010A6   mov         al,byte ptr [edx]//取一个字节
    004010A8   mov         byte ptr [ebp-0Ch],al
        
    004010AB   mov         ecx,dword ptr [ebp-4]//*pStart = *pEnd;
    004010AE   mov         edx,dword ptr [ebp-8]
    004010B1   mov         al,byte ptr [edx]//从pEnd中取一个字节
    004010B3   mov         byte ptr [ecx],al
            
    004010B5   mov         ecx,dword ptr [ebp-8]// *pEnd = chTmp;
    004010B8   mov         dl,byte ptr [ebp-0Ch]
    004010BB   mov         byte ptr [ecx],dl
             
    004010BD   mov         eax,dword ptr [ebp-4]//pStart++;
    004010C0   add         eax,1
    004010C3   mov         dword ptr [ebp-4],eax
              
    004010C6   mov         ecx,dword ptr [ebp-8]//pEnd--;
    004010C9   sub         ecx,1
    004010CC   mov         dword ptr [ebp-8],ecx
    }

    下面是以数组访问的方式:

    //数组访问
    void reverse(char *pStr,int nLen)
    {
     int i = 0;
     int j = nLen-1;
     char chTmp;
     
     while(j>i)
     { 
      chTmp=pStr[i];
      pStr[i]=pStr[j];
      pStr[j]=chTmp;
      
      i++;
      j--;    
     }
    }

    这是上面代码的反汇编

    19:   void reverse(char *pStr,int nLen)
    20:   {
    004010D0   push        ebp
    004010D1   mov         ebp,esp
    004010D3   sub         esp,4Ch
    004010D6   push        ebx
    004010D7   push        esi
    004010D8   push        edi
    004010D9   lea         edi,[ebp-4Ch]
    004010DC   mov         ecx,13h
    004010E1   mov         eax,0CCCCCCCCh
    004010E6   rep stos    dword ptr [edi]
    
    004010E8   mov         dword ptr [ebp-4],0
    
    004010EF   mov         eax,dword ptr [ebp+0Ch]
    004010F2   sub         eax,1
    004010F5   mov         dword ptr [ebp-8],eax
     
    004010F8   mov         ecx,dword ptr [ebp-8]
    004010FB   cmp         ecx,dword ptr [ebp-4]
    004010FE   jle         reverse+6Ah (0040113a)
        
    00401100   mov         edx,dword ptr [ebp+8] <span style="color:#ff0000;">//注意这里</span>
    00401103   add         edx,dword ptr [ebp-4] 
    00401106   mov         al,byte ptr [edx]
    00401108   mov         byte ptr [ebp-0Ch],al
    
    0040110B   mov         ecx,dword ptr [ebp+8] <span style="color:#ff0000;">//注意这里</span>
    0040110E   add         ecx,dword ptr [ebp-4] 
    00401111   mov         edx,dword ptr [ebp+8] <span style="color:#ff0000;">//注意这里</span>
    00401114   add         edx,dword ptr [ebp-8] 
    00401117   mov         al,byte ptr [edx]
    00401119   mov         byte ptr [ecx],al
    
    0040111B   mov         ecx,dword ptr [ebp+8] <span style="color:#ff0000;">//注意这里</span>
    0040111E   add         ecx,dword ptr [ebp-8] 
    00401121   mov         dl,byte ptr [ebp-0Ch]
    00401124   mov         byte ptr [ecx],dl
    
    00401126   mov         eax,dword ptr [ebp-4]
    00401129   add         eax,1
    0040112C   mov         dword ptr [ebp-4],eax
    
    0040112F   mov         ecx,dword ptr [ebp-8]
    00401132   sub         ecx,1
    00401135   mov         dword ptr [ebp-8],ecx
    }

      两个函数反汇编后的代码基本是一致的,但第二段汇编中多了几个add语句, 这是因为在用数组下标的形式访问字符串时,总要对数组的首地址做加减操作才能定位到想要的值, 而指针的实现则一开始就copy了一个首地址,不需要再用加减来定位.显然在这个例子中,用指针来实现reverse函数效率要高.

  • 相关阅读:
    Springcloud学习笔记32--JeecgBoot 注解扫描范围问题(bean扫描不到的问题)
    Springcloud学习笔记31--JeecgBoot 代码生成器一键生成代码(包括:controller、service、dao、mapper、entity、vue)
    Springcloud学习笔记30--JeecgBoot xxl-job定时任务集成和Redisson分布式锁集成
    Springcloud学习笔记29--JeecgBoot 微服务性能测试Jmeter使用
    Springcloud学习笔记28--JeecgBoot 微服务熔断/限流
    Springcloud学习笔记27--JeecgBoot 微服务feign接口调用
    Springcloud学习笔记26--JeecgBoot 新建一个微服务模块,同时配置动态数据源(使用两个数据库)
    Springcloud学习笔记25--JeecgBoot 启动jeecg-demo服务(升级某个模块为微服务模块)
    Springcloud学习笔记24--JeecgBoot 以微服务的方式启动jeecg-system
    Springcloud学习笔记23--application.yml文件的各个配置项及其含义
  • 原文地址:https://www.cnblogs.com/wiessharling/p/3674886.html
Copyright © 2011-2022 走看看