指针访问与数组访问的效率分析
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
我用一个"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语言中字符数组和字符串指针分析
- C---通过指针访问数组
- 指针访问数组
- 指针数组和数组指针的复杂应用分析
- C++语言中数组指针和指针数组彻底分析(系列一)
- JavaScript清空数组的三种方法及效率分析
- 从编译器角度分析C语言中数组名和指针的区别
- C语言中字符数组和字符串指针分析
- 简单分析 指针数组 数组指针 函数指针 函数指针数组 指向函数指针数组的指针
- 数组名与指针典型面试题的分析(转)
- 探讨C++中数组名与指针的用法比较分析
- 用指针访问多维数组中的元素
- 采用指针访问方式从键盘给数组a[N]输入数据,然后对元素值重新按逆序存放并输出 .
- 结构体变量、结构指针变量、结构数组作为函数的参数应用实例分析 .
- C语言中字符数组和字符串指针分析