刚学复习完c语言数组。。现在来总结一下编译器是怎么处理数组的。
我用的是vs2013,其他编译器处理数组的方法可能不一样
//c语言代码
int main()
{
//数组名:arr 元素个数:5
int arr[5] = { 1, 2, 3, 4, 5 };
arr[3] = 9; //修改第四个元素的值
return 0;
}
//汇编代码
//开辟栈空间
001F3050 push ebp
001F3051 mov ebp,esp
001F3053 sub esp,0DCh
//保存需要用到的寄存器
001F3059 push ebx
001F305A push esi
001F305B push edi
//填充堆栈缓冲区
001F305C lea edi,[ebp+FFFFFF24h]
001F3062 mov ecx,37h
001F3067 mov eax,0CCCCCCCCh
001F306C rep stos dword ptr es:[edi]
//分别把每个元素赋值到对应的内存地址
001F306E mov dword ptr [ebp-18h],1
001F3075 mov dword ptr [ebp-14h],2
001F307C mov dword ptr [ebp-10h],3
001F3083 mov dword ptr [ebp-0Ch],4
001F308A mov dword ptr [ebp-8],5
//这里是修改第四个元素的值
013F2331 mov eax,4 //这个4是int数据类型的大小
013F2336 imul ecx,eax,3 //这个3是数组下标
//ecx存的是4字节*第3个数组下标得到的结果是十六进制的C
013F2339 mov dword ptr [ebp+ecx-18h],0 //把0赋值给arr[3]
//这里为什么是[ebp+ecx-18h]呢,看上面[ebp-18h]存的第一个元素的值吧
//因为18h-0xC=C,所以也就是第四个元素的内存地址[ebp-0Ch]
//还原寄存器
001F30A4 pop edi
001F30A5 pop esi
001F30A6 pop ebx
001F30A7 mov esp,ebp //还原栈顶
001F30A9 pop ebp
001F30AA ret //函数返回
上面是一维数组的c语言代码和汇编代码
编译器只是将数组的每个元素放到对应的内存空间中
应该很简单吧........
现在在来看看二维数组编译器是如何处理的
int main()
{
int arr[3][5] = {
{ 1, 2, 3, 4, 5 },
{ 6, 7, 8, 9, 10 },
{ 11, 12,13, 14, 15 }
};
arr[2][3] = 21;
return 0;
}
//汇编代码
//上面解释过的 我就不再次说了
00C222F0 push ebp
00C222F1 mov ebp,esp
00C222F3 sub esp,104h
00C222F9 push ebx
00C222FA push esi
00C222FB push edi
00C222FC lea edi,[ebp+FFFFFEFCh]
00C22302 mov ecx,41h
00C22307 mov eax,0CCCCCCCCh
00C2230C rep stos dword ptr es:[edi]
//分别把每个元素赋值到对应的内存地址
00C2230E mov dword ptr [ebp-40h],1
00C22315 mov dword ptr [ebp-3Ch],2
00C2231C mov dword ptr [ebp-38h],3
00C22323 mov dword ptr [ebp-34h],4
00C2232A mov dword ptr [ebp-30h],5
00C22331 mov dword ptr [ebp-2Ch],6
00C22338 mov dword ptr [ebp-28h],7
00C2233F mov dword ptr [ebp-24h],8
00C22346 mov dword ptr [ebp-20h],9
00C2234D mov dword ptr [ebp-1Ch],0Ah
00C22354 mov dword ptr [ebp-18h],0Bh
00C2235B mov dword ptr [ebp-14h],0Ch
00C22362 mov dword ptr [ebp-10h],0Dh
00C22369 mov dword ptr [ebp-0Ch],0Eh
00C22370 mov dword ptr [ebp-8],0Fh
//这里的14h是arr[3][5]中的5个元素类型的大小 5*sizeof(int)=14h 注意是十六进制的
02C2377 mov eax,14h
//把14h进行左移1位
002C237C shl eax,1
//ecx=[ebp-18h]的内存地址,也就知道了arr数组的行数
002C237E lea ecx,[ebp+eax-40h]
002C2382 mov edx,4 //4就是4个字节因为int类型的大小为4字节
002C2387 imul eax,edx,3 //eax存放的是arr数组的列数
//因为ecx相当于行数,虽然它是一个地址 。eax相当于列数
//可以计算一下ecx==[ebp-18h] eax==C
//[ecx+eax]==[ebp-18h+0xC]结果等于 [ebp-0Ch] 别告诉我你不会算-.-!
002C238A mov dword ptr [ecx+eax],15h //然后赋值为21 十进制的...
00C2238A pop edi
00C2238B pop esi
00C2238C pop ebx
00C2238D mov esp,ebp
00C2238F pop ebp
00C22390 ret
所以呢。。不管在c语言里定义的数组是几维的,编译器会统统看做一维数组来处理的。。
读者若是发现了什么错误,还请多多帮忙指正。。毕竟我也只是个菜鸟。。。