数组
C语言最重要的部分之一
什么是数组?什么情况需要使用数组?
1、比如我们要定义一个变量,来存储一个人的年龄
void main()
{
int age;
reurn;
}
平时我们肯定会这样定义,但是这样只能存储一个,如果我们要存储n个人的年龄呢?
数组定义格式
数据类型 变量名[常量];
数据类型就是我们那些 int、long、short、double等
变量名符合命名规则可以随便写
中括号里的常量,要写定义多少个变量,比如我们存储5个人的年龄
void main()
{
int age[5]; //定义数组完成
reurn;
}
数组就是一堆变量声明到了一起
数组的初始化
未初始化的数组:
不给初始化数值的话,会使用堆栈默认填充的值:CC
初始化后的数组:
1、如上图所示,1放入了ebp-14,2放入了ebp-10因为我们定义在了函数内,局部变量,都是在堆栈中分配的,所以不是一个地址,而是一个寄存器寻址。如果放到了全局,就不会是ebp-14 -10,而是一个绝对地址。
初始化的两种方式
int age[5] = {1,2,3,4,5};
int age[] = {1,2,3,4,5};
不管数组后面写不写数量,计算机都会根据后面赋值内容进行检测生成。
2. 数组的读写
如果我们用了:
int age[5];
我们暂时不想让数组卡到某一个值,等用到的时候在进行赋值
等我们用到的时候可以用如下方式写入数据:
void main()
{
int age[5];
age[0] = 1;
age[1] = 2;
return;
}
再来看下写入数据后的汇编代码。
和直接进行初始化的汇编代码一样。
为什么写age[0]
数组下标从0开始,也就是5个数据的编号:0、1、2、3、4如果写了5,就会抛出异常。
那么怎么读取数据?
void main()
{
int age[5];
age[0] = 1;
age[1] = 2;
int a; //定义变量a
a = age[0]; //a接收数组中的第一个数据
return;
}
3. 多维数组
多维数组的定义:
比如,我们班级有5个小组,每个小组有2个人,我们要存储这5个小组,10个人的年龄。
1、比如我们上面写的单维数组,那么我们就只能这么写
int a[10]或者a[2*5]
2、但是用多维数组,我们可以像以下方式进行书写
int a[5][2]
那么再例如:
我们家里有一栋楼房,这栋楼房里有20个房间,每个房间里面住了8个人
我们就可以写 int a[1*20*8]
或者int a[1][20][8]
int a[1][20][8]就叫做多维数组
那么二维数组如何像一维数组那样进行初始化?
int a[5] = {0,1,2,3,4};
那么二维数组呢?
还是,我们有3个房间,每个房间里面2个人
int a[3][2]={
{16,18},
{24,27},
{57,65}
};
1、三个花括号,代表我们的三个房子,最大的那个花括号,代表整体
2、每个房子里面有2个人,所以,我们给三个房间里的人分配了年龄。
int a[3][2]={ //大整体
{16,18}, //每个括号就代表每个房子
{24,27}, //每个房子里面两个人,所以24,27年龄。
{57,65}
};
二维数组在内存的布局
不管几维数组,在内存中的布局,全都是连续存储。
就像这样,三个房间,每个房间两个人,连续存储方式。
看一维和二维数组的汇编代码:
// int a[6] = {1,2,3,4,5,6};
0040D728 mov dword ptr [ebp-18h],1
0040D72F mov dword ptr [ebp-14h],2
0040D736 mov dword ptr [ebp-10h],3
0040D73D mov dword ptr [ebp-0Ch],4
0040D744 mov dword ptr [ebp-8],5
0040D74B mov dword ptr [ebp-4],6
/*
int a[3][2] = {
{1,2},
{3,4},
{5,6}
};
*/
00401028 mov dword ptr [ebp-18h],1
0040102F mov dword ptr [ebp-14h],2
00401036 mov dword ptr [ebp-10h],3
0040103D mov dword ptr [ebp-0Ch],4
00401044 mov dword ptr [ebp-8],5
0040104B mov dword ptr [ebp-4],6
发现多维数组和一维数组并无区别。
那么都一样,为什么还要使用多维数组?
比如,a[20] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20}
这样取出数据的时候可能你知道是第几个,如果乱序呢?是不是要自己算?
如果
a[4][5]={
{1,2,3,4,5},
{6,5,4,3,2},
{2,5,6,9,7},
{1,9,4,7,7}
};
这样多维数组去取数据,我们要取出第十四个数据,那么五个一列就是第三列的第四个
int b = a[2][3]
二维数组的读写
比如:
本课程一共有5章,每章10课
int kecheng[5][10]={
{1,2,1,3,5,6,8,9,7,4}, //下标0
{9,6,3,4,5,8,6,4,2,3}, //1
{7,9,5,4,3,8,1,4,9,6}, //2
{8,6,3,4,2,1,9,9,8,6}, //3
{3,4,8,5,1,4,7,9,6,3} //4
};
那么我们想取第4章的第7课怎么写?
a[3][6]
我们想看第1章的第1课
a[0][0]
那么我们的数据存到内存中,都是连续存储的,不会像我们的代码一样,很容易看懂!
编译器是怎么帮我们找到这个数据的?
a[310+6] = a[36]也就是数组的第36个数据
那么我们核对一下,第一排09,第二排1019,第三排2029,第四排3039,那么也就是1后面的那个9,第36个数
a[010+0] = a[0]
这个就是0,下标全是0,就是第一排的第一个,1
这就是编译器帮我们找数值的算法。
编译器如何计算?
a[0][2][2] 第一章节,第三节课,第三个人
a[043+23+2]
那么我们想查看第3章节的,第2节课的,第1个人。
编译器公式:a[243+13+0]