http://wenku.baidu.com/view/e180b4df5022aaea998f0f36.html
这篇文章上关于堆和栈的区别加以阐述,其中提到的堆与栈的存储效率的地方,通过自己查看汇编代码,把自己的理解汇总如下,算是对以上这篇文章的补充:
还是引用这个经典的例子:
#include <stdio.h>
void main()
{
char a = 1;
char c[] = "1234567890";
char *p ="1234567890";
a = c[1];
a = p[1];
return;
}
整个代码的反汇编代码如下:
1: #include <stdio.h>
2: void main()
3: {
00401010 push ebp
00401011 mov ebp,esp
00401013 sub esp,54h
00401016 push ebx
00401017 push esi
00401018 push edi
00401019 lea edi,[ebp-54h]
0040101C mov ecx,15h
00401021 mov eax,0CCCCCCCCh
00401026 rep stos dword ptr [edi]
4: char a = 1;
00401028 mov byte ptr [ebp-4],1
5: char c[] = "1234567890";
0040102C mov eax,[string "1234567890" (0042201c)]
00401031 mov dword ptr [ebp-10h],eax
00401034 mov ecx,dword ptr [string "1234567890"+4 (00422020)]
0040103A mov dword ptr [ebp-0Ch],ecx
0040103D mov dx,word ptr [string "1234567890"+8 (00422024)]
00401044 mov word ptr [ebp-8],dx
00401048 mov al,[string "1234567890"+0Ah (00422026)]
0040104D mov byte ptr [ebp-6],al
6: char *p ="1234567890";
00401050 mov dword ptr [ebp-14h],offset string "1234567890" (0042201c)
7: a = c[1];
00401057 mov cl,byte ptr [ebp-0Fh]
0040105A mov byte ptr [ebp-4],cl
8: a = p[1];
0040105D mov edx,dword ptr [ebp-14h]
00401060 mov al,byte ptr [edx+1]
00401063 mov byte ptr [ebp-4],al
9: return;
10: }
00401066 pop edi
00401067 pop esi
00401068 pop ebx
00401069 mov esp,ebp
0040106B pop ebp
0040106C ret
这里“1234567890”是一个字符串常量,存放的位置在常量数据区(既不是堆也不是栈),此处的地址为0042201c
也就是说编译的时候这个字符串常量已经确定了,
针对这个例子
char c[] = "1234567890";
char *p ="1234567890";
前后两个“1234567890”就是同一个字符串常量,存放在编译时确定的常量数据区里,
运行的时候再用这个常量字符串对c赋值,而第二种使用的时候先把指针值读到edx中,再根据edx读取字符。
如果换成下面的例子:
char c[] = "aaaaa";
char *p ="1234567890";
因为两个字符串不同,就存在常量数据区的不同位置。
汇编部分如下:
5: char c[] = "aaaaa";
0040102C mov eax,[string "aaaaa" (00422028)]
00401031 mov dword ptr [ebp-0Ch],eax
00401034 mov cx,word ptr [string "aaaaa"+4 (0042202c)]
0040103B mov word ptr [ebp-8],cx
6: char *p ="1234567890";
0040103F mov dword ptr [ebp-10h],offset string "1234567890" (0042201c)