我们都知道,数组是C语言里存储数据的重要工具,更是实现排序、切片(利用循环将一个大数字的每一位存储到一个数组中)的好帮手。
一、什么是数组?
数组是一组相同类型元素的集合,这在我们初始化一个数组的时候就能看出来。
中括号内为数组元素个数最大值。
存储整型,我们就利用int;字符,就用char。一切按照需要来定义数组内元素类型;
但我们需要注意的是:
- 数组中存放的是1个或多个数据,但是数组元素个数不能为0。
- 数组中存放的多个数据,类型必须是相同的。
数组分为一维数组和多维数组。
二、一维数组
数组最简单的类型便是一维数组,而且刚刚举出的例子便是一个一维数组。
你还可以写:
char arr[20]={0};
double score[10]={0};
等等。
如何对一维数组初始化?
对数组的初始化,分为两类,完全初始化和不完全初始化。而一维数组初始化的值往往用大括号括起来。
完全初始化
int arr[3]={1,2,3};//因为初始化给出的元素个数等于数组元素个数最大值,所以称为完全初始化。
不完全初始化
int arr[3]={0};//这种初始化,会使得一维数组储存给定的值,其余元素均为0直到填满整个数组为止。
错误的初始化
int arr[3]={1,2,3,4};//错误的原因是储存的数据超过了一维数组长度,一维数组储存不了。
一维数组的下标
既然储存了数据,我们就有要将数据取出来用的那一刻,那么这个时候,一维数组的下标就出现了。
C语言中数组的访问提供了一个操作符[ ],称为下标引用操作符。
比如我们定义了一个长度为3的数组。
int arr[3]={1,2,3};
我们需要取用3的时候,就可以用arr[2]提取出来。
可能有人会疑惑为什么是arr[2]而不是arr[3]?
这是因为数组的下标从0开始向右逐次加1,这就导致了长度为3的数组,最右边的数据下标为2。
这也是我们在循环取用/循环储存的时候需要注意的点。
不能写成i=1,而得写成i=0
也不能写成i=n,而得写成i=n-1
第n个对应a[n-1]
一维数组在内存中的储存
我们可以在打印的时候,加上取地址符"&",就能得到数组元素的地址。
比如:
(其中%p是输出地址格式符)
我们可以发现,一维数组随着下标变大,地址也变大,而且每个地址之间相差4,这证明了地址是连续存放的(因为一个整型4个字节)
三、多维数组
多维数组和一维数组的本质是相同的。
以二维数组为例,来解释这句话。
二维数组的初始化
二维数组和一维数组的初始化方式是相同的,仍然是中括号放数组元素最大个数,大括号放数据。
唯一的区别是,二维数组多出了行与列的概念。
因为二维数组在理解中,往往是这样的:
[ 1 3 5 7 9
2 4 6 8 10
5 6 7 11 21]
如图展示的是一个三行五列的二维数组。
我们可以用int arr[3][5]来表示
其中[3]是行数,[5]是列数。
完全初始化
int arr[2][4]={1,2,3,4,5,6,7,8};
如果画出图来表示,就是1234会放在第一行,5678放在第二行。
但我们往往更推荐这么写:
int arr[2][4]={{1,2,3,4},{5,6,7,8}};
红色大括号表示这是一行内的数据。
因为如果数据多的话,我们经常会数不清楚到底这个是第几行第几列,所以我们用大括号分隔开,代码的可读性大大增加了。
不完全初始化
int arr[2][4]={1,2};
这个时候只会在第0行的第0列和第1列分别放入1和2,其余均填充0。(下标会在后面补充到)
二维数组中,我们也可以按照行来初始化
int arr[2][4]={{1,2},{3,4}}
这个时候只有第0行的第0列和第1列,第1行的第0列和第1列才有值,其余均填充0。
初始化可以省略行,但不能省略列
C语言会帮我们自动扩充行以放入所有元素,但不能省略列。
二维数组的下标
C语言规定,二维数组的行是从0开始的,列也是从0开始的。
所以我们同样需要注意之前叙述的数组下标问题,切记从0开始!!!
二维数组在内存中的储存
我们再次使用之前在一维数组中使用过的操作。
我们同样可以得到与一维数组一致的结论。
一维数组随着下标变大,地址也变大,而且每个地址之间相差4,这证明了二维数组的地址是连续存放的(跨行处的两个元素亦是相差4)
这是不是提醒了我们什么神奇的东西?
理解二维数组/多维数组的新角度
arr[2][4]这样一个数组,我们似乎可以理解为两个一维数组被摆放在了一起。(因为地址是相邻的)
arr[1][4],arr[2][4]
我们将arr[1]和arr[2]看成变量名,这样二维数组就被强行拆解为一维数组。
由此,我们也可以这样理解,三维,四维等更多维的数组,都可以依此“降维”。
四、变长数组
C99中,出现了一个变长数组(variable-length array, 简称VLA),允许我们可以使用变量指定数组大小。
int arr[n];
由于事先不知道n的值,只有等我们赋值/输入的时候才能知道该数组的长度,所以我们并不能对其进行初始化。
虽然名字是变长数组,但是长度一旦确定,就无法改变,和java的自动扩容还是有很大的区别。
英语好的朋友也可以从全称中看出,其真名应该叫以变量大小为长度的数组才更为合适。
友情提示:VS2022中不可以使用变长数组,但是其他编译器如小熊猫,还有大部分oj均可以使用,所以还是需要知道的。