数组顾名思义就是一堆数据组成的
- 把具有相同数据类型的若干变量按有序的形式组织起来,
以便于程序处理,这些数据元素的集合就是数组,按照数组元素的类型不同,可分为:数值数组、字符数组、指针数组 - 数组的应用场景就是用来保存多个数据类型相同的变量
数组的优点:数组是将元素在内存中连续存储的;
因为数据是连续存储的,内存地址连续,所以在查找数据的时候效 率比较高;
缺点:在存储之前,我们需要申请一块连续的内存空间,并且在编译的时候就必须确定好它的空间的大小。在运行的时候空间的大小是无法随着你的需要进行增加和减少而改变的,当数据两比较大的时候,有可能会出现越界的情况,数据比较小的时候,又有可能会浪费掉内存空间。在改变数据个数时,增加、插入、删除数据效率比较低
- 数组的定义 ==> 数据类型 数组名称 元素个数 例如:int arr[5];
上面的意思是申请了一个整形类型的数组里面可以存放五个元素
数组的定义和初始化几种样子
- int arr[3] = {4, 6, 9}; 指定元素个数,完全初始化
- int arr[] = {4, 6, 9}; 不指定元素个数,完全初始化
- int arr[5] = {1,2}; 指定元素个数,部分初始化
- int arr[5] = {[4] = 3,[1] = 2}; 指定元素个数,部分初始化
- int arr[] = {[4] = 3}; 不指定元素个数,部分初始化
- int arr[3];先定义后初始化
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
如果定义了数组,但没有给数组内的元素赋值,那么数组中没有赋值的元素将存储的回事垃圾数据
数组的注意点:
使用数组时不能超出数组的索引范围使用, 索引从0开始, 到元素个数-1结束
使用数组时不要随意使用未初始化的元素, 有可能是一个随机值
对于数组来说, 只能在定义的同时初始化多个值, 不能先定义再初始化多个值
数组的调用
- int arr[5] = {5,2,3,1,6};这五个数的索引分别是01234;
假如我想要拿出元素2那么就 arr[1] 拿出元素6就是 arr[4] - 数组的遍历
int ages[4] = {19, 22, 33, 13};
for (int i = 0; i < 4; i++) { printf("ages[%i] = %i\n", i, ages[i]); }
计算数组的总长度:sizeof(数组名称)
这是计算一个数组的总占量
sizeof(数组名称[0])
计算数组里面单个元素占用的量
总占用量除以单个占用量就是这个数组的长度
正序输出数组
数组在内存中的存储与分配空间
- 1.内存寻址中,从高到低分配一块连续没有被使用的内存给数组
- 2.从分配的连续存储空间中, 从地址小的位置开始给每个元素分配空间
- 3.从每个元素分配的存储空间中, 地址最大的位置开始存储数据
- 4.数组名指向的是内存地址最小的那块空间
-
字符在内存中是以对应ASCII码值的二进制形式存储的,而非上述的形式。
数组的越界问题
数组越界导致的问题:
约错对象
程序崩溃
数组可以作为函数的参数使用,数组用作函数参数有两种形式:
一种是把数组元素作为实参使用
一种是把数组名作为函数的形参和实参使用
在C语言中,数组名除作为变量的标识符之外,数组名还代表了该数组在内存中的起始地址,因此,当数组名作函数参数时,实参与形参之间不是"值传递",而是"地址传递"
实参数组名将该数组的起始地址传递给形参数组,两个数组共享一段内存单元, 系统不再为形参数组分配存储单元
既然两个数组共享一段内存单元, 所以形参数组修改时,实参数组也同时被修改了
数组名作函数参数的注意点
- 在函数形参表中,允许不给出形参数组的长度
- 形参数组和实参数组的类型必须一致,否则将引起错误。
- 当数组名作为函数参数时, 因为自动转换为了指针类型,所以在函数中无法动态计算除数组的元素个数