您的位置:首页 > 其它

指针访问与数组访问的效率分析

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

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

[cpp]
view plaincopy

//指针访问  
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下的反汇编代码,我加了一些注释方便理解

[cpp]
view plaincopy

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  
}  

 

[cpp]
view plaincopy

//数组访问  
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--;      
 }  
}  

 

这是上面代码的反汇编

[cpp]
view plaincopy

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] //注意这里

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]//注意这里
0040110E   add         ecx,dword ptr [ebp-4]   
00401111   mov         edx,dword ptr [ebp+8]
//注意这里
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] //注意这里
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函数效率要高.

转自:http://blog.csdn.net/pony_maggie/article/details/6748662
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  汇编 c