二维数组
让我们先定义一个二维数组
int arr[3][3] = {
{ 1,2,3 },
{ 4,5,6 },
{ 7,8,9 }
};
//3行3列,第一个3代表了一共有3行,第二个3代表了一行里一共有多少个数据
int arr[4][5]={
{1, 2, 3, 4, 5},
{6, 7, 8, 9, 10},
{11,12,13,14,15},
{16,17,18,19,20}
};
//4行5列,以此类推
废话不多说,先上反汇编
int arr[3][3] = {
{ 1,2,3 },
001717C8 C7 45 D8 01 00 00 00 mov dword ptr [arr],1
001717CF C7 45 DC 02 00 00 00 mov dword ptr [ebp-24h],2
001717D6 C7 45 E0 03 00 00 00 mov dword ptr [ebp-20h],3
{ 4,5,6 },
001717DD C7 45 E4 04 00 00 00 mov dword ptr [ebp-1Ch],4
001717E4 C7 45 E8 05 00 00 00 mov dword ptr [ebp-18h],5
001717EB C7 45 EC 06 00 00 00 mov dword ptr [ebp-14h],6
{ 7,8,9 }
001717F2 C7 45 F0 07 00 00 00 mov dword ptr [ebp-10h],7
001717F9 C7 45 F4 08 00 00 00 mov dword ptr [ebp-0Ch],8
00171800 C7 45 F8 09 00 00 00 mov dword ptr [ebp-8],9
};
让我们看看昨天的一维数组-C语言再学习之数组
惊奇的发现,二维数组和一位数组好像一样?实验一下
int arr2[9] = { 1,2,3,4,5,6,7,8,9 };
009A4DB8 C7 45 D8 01 00 00 00 mov dword ptr [arr2],1
009A4DBF C7 45 DC 02 00 00 00 mov dword ptr [ebp-24h],2
009A4DC6 C7 45 E0 03 00 00 00 mov dword ptr [ebp-20h],3
009A4DCD C7 45 E4 04 00 00 00 mov dword ptr [ebp-1Ch],4
009A4DD4 C7 45 E8 05 00 00 00 mov dword ptr [ebp-18h],5
009A4DDB C7 45 EC 06 00 00 00 mov dword ptr [ebp-14h],6
009A4DE2 C7 45 F0 07 00 00 00 mov dword ptr [ebp-10h],7
009A4DE9 C7 45 F4 08 00 00 00 mov dword ptr [ebp-0Ch],8
009A4DF0 C7 45 F8 09 00 00 00 mov dword ptr [ebp-8],9
让我们来对比一下堆栈操作
int arr2[3][3] = { 1,2,3,4,5,6,7,8 };//多维数组使用一维数组的方式赋值!
结论:在我们眼中,多维数组和一维数组的存储方式一模一样!
使用多维数组:
二维数组的赋值
int arr[3][3] = {0};
int arr3[3 * 3] = {0};
int arr3[9] = {0};
//无论数组怎么赋值,在堆栈中的结构永远不变!否则就不叫数组了
既然多维数组可以使用一维数组的 方式来访问,而且多维数组在底层和一维数组一样,那么我们可以不可以使用一维数组的方式来访问多维数组?
先思考一下,如果arr[3][3]我们要访问arr第四个值,那么得到的值应该是第二行的第一个,也就是arr[2][1],如果我们使用arr[4]应该也可以访问到
猜测一下,arr[2][1]的opcode是
mov dword ptr [ebp-18h],5
//那么我们的arr[2][1]读取的代码就应该是一样的!
int b = 0;
010B4DF7 C7 45 CC 00 00 00 00 mov dword ptr [b],0
b=(int )arr[2][1];
010B4DFE B8 0C 00 00 00 mov eax,0Ch
010B4E03 D1 E0 shl eax,1
010B4E05 8D 4C 05 D8 lea ecx,arr[eax]
010B4E09 BA 04 00 00 00 mov edx,4
010B4E0E C1 E2 00 shl edx,0
010B4E11 8B 04 11 mov eax,dword ptr [ecx+edx]
010B4E14 89 45 CC mov dword ptr [b],eax
//通过昨天的练习得知,imul其实就是计算下标而已,使用arr[4]来查找数组,
既然编译器都帮我们使用了arr[4],那我们直接使用arr[4]又能不能读取arr[2][1]呢?
b = (int)arr[4];
01304E98 B8 0C 00 00 00 mov eax,0Ch
01304E9D C1 E0 02 shl eax,2
01304EA0 8D 4C 05 D4 lea ecx,arr[eax]
01304EA4 89 4D C8 mov dword ptr [b],ecx
//分析汇编发现,这里仅仅是把arr[4]的地址给了b!
再来看看arr[4]是什么鬼
lea ecx,dword ptr ss:[ebp+eax-2C]
arr[30]....
总结:无论多少维数组,在内存中都是连续排列,可以使用堆栈来访问数组的值