一、二维数组
1.二维数组分配空间
-
不管是一维还是多维数组,编译器分配的空间是无差别的,定义成多维的,只是方便开发人员管理数据时更加直观
-
如何分配空间的:
-
代码如下
int arr[3][4] = { {1,2,3,4}, {5,6,7,8}, {9,7,6,5} }; //int arr[3*4] = {1,2,3,4,5,6,7,8,9,7,6,5};
-
对于一维数组,编译器先计算数组的长度决定开辟多少缓冲区,接着将数组中的数据正着从低地址向高地址存到缓冲区中
-
对于二维数组,编译器同样也是先计算数组的长度,会将两个
[]
中的长度相乘得到数组的长度–3 * 4 = 12,且是int类型的数据,所以12 * 4 = 48 = 0x30,所以VC6编译器会开辟缓冲区大小也同样为0x40 + 0x30 = 0x70字节,而且虽然定义时是四个四个一组,一共三组,但是对编译器来说一维还是多维是无差别的,还是按照将数组中的数据正着从低地址向高地址存到缓冲区中 -
所以二维数组还可以省略当中的
{}
,编译器也会根据定义数组后面的[][]
中的数值自动分组计算大小int arr[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12}; int arr[3][4] = {1,2,3,4,5,6,7,8,9,10}; //补0
-
-
当给定部分值时,没赋初始值的元素默认为0,反汇编如下
int arr[3][4] = { {1,2}, {5}, {9} };
-
二维数组定义时还可以省略第一个
[]
中的数值,编译器会自动根据第二个[]
中数决定将后面的元素几个分一组,凑够一组中的个数,再凑后面几个数,最后不够一组中的数了就用0补int arr[][4] = {1,2,3,4,5,6,7,8,9,10,11}; //1,2,3,4 5,6,7,8 9,10,11,0所以二维数组长度为12字节
2.编译器获取元素
-
定义一个二维数组为:
int arr[5][12] = { {1,2,1,4,5,6,7,8,99,1,2,3}, //0 {1,2,1,4,5,6,7,88,9,1,2,3}, //1 {1,2,1,4,5,6,7,8,9,1,2,3}, //2 {1,2,1,4,5,6,7,8,9,1,2,3}, //3 {1,2,1,4,5,6,7,8,9,1,2,3}, //4 // 0 1 2 3 4 5 6 7 8 9 10 11 }; int i = arr[0][8]; int j = arr[1][7];
-
如果现在我要得到
arr[0][8]
中的值,那么可以理解为找第1行第9个值,所以就是99;那么编译器是如何找到呢? -
我们知道编译器是不分行和列的概念的,它只管正着从低地址向高地址存,所以编译器其实是根据[ebp - 0xF0 + (0 * 0xC + 0x8) * 0x4] = [ebp - 0xD0]得到的
arr[0][8]
中的值,即先找到数组中第一个元素的存储地址[ebp - 0xF0],然后根据下标做运算得到结果[ebp - 0xD0] -
找
arr[1][7]
同理,[ebp - 0xF0 + (0x1 * 0xC + 0x7) * 0x4] = [ebp - 0xA4],所以编译器会根据[ebp - 0xA4]找到arr[1][7]
中的值。我们的角度来说就是找第二行第8个元素,即88
二、作业
1.二维数组正向练习
-
练习一:假设现在有5个班,每个班10个人,设计一个二维数组存储这些人的年龄
#include "stdafx.h" void Func(){ int age[5][10] = { {1,2,3,4,5,6,7,8,9,10}, {1,2,3,4,5,6,7,8,9,10}, {1,2,3,4,5,6,7,8,9,10}, {1,2,3,4,5,6,7,8,9,10}, {1,2,3,4,5,6,7,8,9,10} }; } void main(int argc,char* argv[]){ Func(); }
-
练习二:如果想知道第二个班的第6个人的年龄,应该如何获取?编译器该如何获取?
#include "stdafx.h" void Func(){ int age[5][10] = { {1,2,3,4,5,6,7,8,9,10}, {1,2,3,4,5,6,7,8,9,10}, {1,2,3,4,5,6,7,8,9,10}, {1,2,3,4,5,6,7,8,9,10}, {1,2,3,4,5,6,7,8,9,10} }; printf("%d",age[1][5]); } void main(int argc,char* argv[]){ Func(); }
-
编译器获取
age[1][5]
则是根据[ebp - 0xC8 + (1 * 0xA + 0x5) * 0x4] = [ebp - 0x8C],即从[ebp - 0xB9]中取出当中的值
-
-
练习三:打印所有班级,所有学生的年龄(每个班级打印一行)
#include "stdafx.h" void Func(){ int age[5][10] = { {1,2,3,4,5,6,7,8,9,10}, {1,2,3,4,5,6,7,8,9,10}, {1,2,3,4,5,6,7,8,9,10}, {1,2,3,4,5,6,7,8,9,10}, {1,2,3,4,5,6,7,8,9,10} }; for(int i = 0;i < 5;i++){ for(int j = 0;j < 10;j++){ printf("%d ",age[i][j]); } printf("\n"); } } void main(int argc,char* argv[]){ Func(); getchar(); }
-
练习四:将第二个班级的超过20岁的学生的年龄修改为21岁
#include "stdafx.h" void Func(){ int age[5][10] = { {1,2,3,4,5,6,7,8,9,10}, {1,28,3,45,5,63,7,84,9,10}, {1,2,3,4,5,6,7,8,9,10}, {1,2,3,4,5,6,7,8,9,10}, {1,2,3,4,5,6,7,8,9,10} }; for(int i = 1,int j = 0;j < 10;j++){ if(age[1][j] > 20){ age[1][j] = 21; } } //验证一下 for(int i = 0;i < 5;i++){ for(int j = 0;j < 10;j++){ printf("%d ",age[i][j]); } printf("\n"); } } void main(int argc,char* argv[]){ Func(); getchar(); }
-
练习五:打印出每个班级学生的年龄的和
#include "stdafx.h" void Func(){ int sum = 0; int age[5][10] = { {1,2,3,4,5,6,7,8,9,10}, {1,28,3,45,5,63,7,84,9,10}, {1,2,3,4,5,6,7,8,9,10}, {1,2,3,4,5,6,7,8,9,10}, {1,2,3,4,5,6,7,8,9,10} }; for(int i = 0;i < 5;i++){ for(int j = 0;j < 10;j++){ sum += age[i][j]; } } printf("%d",sum); } void main(int argc,char* argv[]){ Func(); getchar(); }
2.数组算法练习
-
数组一:[3,5,7,9,12,25,34,55];数组二:[4,7,9,11,13,16],将两个数组中所有数据进行从小到大的排序,存储到另一个数组中
#include "stdafx.h" void Func(){ int arr1[8] = {3,5,7,9,12,25,34,55}; //这两个数组中的元素都是排序好的 int arr2[6] = {4,7,9,11,13,16}; int arr3[14] = {0}; int i = 0; int j = 0; int k = 0; for(;i < 8;i++){ for(;j < 6;j++){ if(arr1[i] < arr2[j]){ arr3[k++] = arr1[i]; break; }else if(arr2[j] < arr1[i]){ arr3[k++] = arr2[j]; }else{ arr3[k++] = arr1[i]; arr3[k++] = arr2[j]; j++; break; } } if(j == 6){ arr3[k++] = arr1[i]; } } for(k = 0;k < 14;k++){ printf("%d ",arr3[k]); } } void main(int argc,char* argv[]){ Func(); getchar(); }