10.1.明确:计算机程序最终玩内存,玩内存首先得分配
定义变量,例如:
int a;
int b;
int c;
...
int aa;
...
int zzzzz.....;
前提是数据类型一致,并且大量的分配,但是此种分配方法让代码极其繁琐
问:是否存在一种方法解决此类问题:既可以保证数据类型一致又可大量一次性分配大量内存呢?
答:有,这就是C语言的分配内存方法2:数组
10.2.数组的定义:是一种分配内存的方法,分配的内存能够存储多个类型相同的数据
10.3.数组的优缺点:
优点:能够大量分配内存
缺点:数据类型必须相同,因为有些场合需要数据类型不一样,例如:分数(浮点数)和年龄(整数)
必须一次性分配好,不能做到随时用随时分配
10.4.数组分配内存的语法格式:简称定义数组的语法格式
元素数据类型 数组名[长度(又称数组元素个数)] ={初始化列表(如果有多个,用逗号,分开)};
例如:
int a[5] = {1,2,3,4,5};
语义:连续分配5个元素的内存空间,并且每个元素的数据类型为int,每个元素占4字节
内存空间,所以最终连续分配了20个字节内存空间,并且每个元素的值分别是1,2,3,4,5
类似:int a = 1, b = 2, c = 3, d = 4, e = 5;
10.5.数组特点
1)数组分配的内存是连续的
2)数组名就是整个数组的首地址,等于数组第0个元素的首地址
3)数组的长度又称数组元素的个数,而不是整个数组分配内存的大小
例如:int a[5]; 数组长度=数组元素个数=5,分配的内存大小为20字节
4)数组下标就是数组中元素的编号(专业术语索引号index),下标从0开始
int a[5] = {1,2,3,4,5};
元素数值 下标
1 0
2 1
3 2
4 3
5 4
5)数组中元素的访问是通过运算符"[]"和下标来进行访问
格式:数组元素=数组名[下标]
例如:int a[5] = {1,2,3,4,5};
第0个元素:a[0] = 1
第1个元素:a[1] = 2
第2个元素:a[2] = 3
第3个元素:a[3] = 4
第4个元素:a[4] = 5
打印第3个元素的值:printf("%d\n", a[3]);
将第3个元素的值修改为250:a[3] = 250;
6)切记切记切记:千万注意数组的越界访问(笔试题必考)访问了不该访问的内存
例如:int a[5] = {1,2,3,4,5}; //目前操作系统给你分配的有效内存为20字节,5个元素
printf("%d\n", a[4]); //打印第4个元素的值,合法
printf("%d\n", a[5]); //打印不存在第5个元素的值,理论上越界了,但是程序没有崩溃
//打印什么值不清楚,不崩溃是因为仅仅查看内存的信息而已
a[5] = 250; //越界访问,此时程序崩溃,250数字有可能修改了操作系统最核心的程序
10.6.数组定义形式:
形式1:int a[5] = {1,2,3,4,5};
形式2:int a[5] = {1,2,3}; a[0]=1,a[1]=2,a[2]=3,a[3]=a[4]=0,没有初始化一律给0
形式3:int a[5] = {0}; 全是0
形式4:int a[5] = {}; 全是0
形式5:int a[5]; 只定义没有初始化,结果都是随机数,很危险
形式6:int a[] = {1,2,3,4,5}; 元素个数为5个
形式7:int a[5] = {1,2,3,4,5,6,7,8}; gcc直接将无效元素忽略,6,7,8不要
注意:错误形式:int a[]; gcc迷茫了,编译不通过,报错
10.7.求数组元素个数公式:元素个数=sizeof(数组名)/sizeof(数组的第0个元素)
例如:int a[5] = {1,2,3,4,5};
数组首地址=a=&a[0]
数组占用的内存大小=sizeof(a)=20
第0个元素占用的内存大小=sizeof(a[0])=4
元素个数=sizeof(a)/sizeof(a[0])=5个
10.8.变长数组(了解即可)
a)定义:数据元素个数不定
例如:
int a[5]; //定长数组,长度固定,gcc将来连续分配20个字节内存
int len;
int a[len]; //变长数组,不可初始化
scanf("%d", &len);
10.9.多维数组(重点研究二维数组,上面讲的都是一维数组)
a)二维数组的定义: 由多个一维数组组成的数组,二维数组的每个元素是一个数组
二维数组的本质还是一维数组,只是形式上将一维数组再次分组而已
b)定义二维数组语法:数组元素类型 二维数组名[二维数组长度][一维数组长度] = {初始化表};
例如:int a[5][10];
语义:
1.a代表是一个包含5个元素的数组,其中每个元素都是一个包含10个元素的数组
其中每个元素的数据类型为int
所以a就是二维数组的首地址
2.a[0]代表a的第0个元素,而第0个元素又是一个一维数组
所以a[0]就是一个一维数组,并且是一维数组的首地址
3.a[0][0]代表a的第0个一维数组元素的第0个元素
所以a[0][0]就是二维数组中的某个元素
4.统一:a[i][j]代表a的第i个一维数组元素的第j个元素
c)定义二维数组的形式:
形式1:int a[3][4]; //只定义不初始化,随机数
形式2:int a[3][4] = {{1,2,3,4},{4,3,2,1},{2,1,3,4}};
形式3:int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
形式4:int a[3][4] = {0};
形式5:int a[3][4] = {{1,2},{0}};
形式6:int a[][4] = {1,2,3,4,5,6,7,8}; 等价于int a[2][4]
形式7: int a[2][3] = {{1,2},{3,4},{5,6}}; //错误,越界
注意:二维数组长度可以省略,但是一维数组的长度不可省略(gcc会很迷茫)
例如:
int a[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
printf("%d\n", a[2][3]); //12
printf("%d\n", a[0][3]); //4
printf("%d\n", a[1][2]); //7
a[2][2] = 250; //11->250
d)二维数组终极公式:
例如:int a[2][3] = {0};
a是二维数组的首地址=&a[0][0]
sizeof(a):获取整个二维数组占用的内存大小
sizeof(a[0]):获取二维数组中第0个一维数组元素占用的内存大小
sizeof(a[0][0]):获取二维数组中第0个一维数组中第0个元素占用的内存大小
sizeof(a)/sizeof(a[0]):获取二维数组的长度
sizeof(a[0])/sizeof(a[0][0]):获取一维数组的长度