C语言再学习6-多维数组

二维数组

让我们先定义一个二维数组

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]....

总结:无论多少维数组,在内存中都是连续排列,可以使用堆栈来访问数组的值



猜你喜欢

转载自blog.csdn.net/qq_35425243/article/details/82850054