1.何为数组?

数,代表数据;组,代表小组、集合。

数组,就是一堆数据的集合

1
2
1 // 一个数据
{1,2,3,4} // 一个数组(数据的集合)

上面的{1,2,3,4},就是一个int类型的数组。

2.数组定义语法

数组的声明语法如下,在变量名后带上中括号[],即代表这是一个数组。

1
类型名 数组名[数组长度]; // 声明一个对应类型的数组

下面是几个数组声明的例子

1
2
3
int arr1[10];    // 声明一个能存放10个int类型的整形数组
char arr2[20]; // 声明一个能存放20个char类型的字符数组
double arr3[30]; // 声明一个能存放30个double类型的浮点数数组

除了上方的方式,在声明数组的时候,我们还可以不带中括号中的数字,让操作系统根据我们的赋值来自动初始化对应长度的空间;

1
2
3
4
5
6
// 编译器会自动创建一个能存放4个int类型的数组,等价于int arr4[4]
int arr4[] = {1,2,3,4};
// 编译器会自动创建一个能存放6个char类型的数组,等价于char arr5[6]
char arr5[] = "hello"; // 这里末尾还有一个隐藏的\0,会在字符串章节详解
// 编译器会自动创建一个能存放3个float类型的数组,等价于float arr6[6]
float arr6[] = {1.2,3.4,5.4};

另外,我们还能带上中括号中的长度数字,再赋值一部分,或完全赋值;

1
int arr7[10] = {1,2,3,4,5};  // 只初始化5个数字

需要注意的是,这里相当于只初始化了前5个值,此时后5个空间是未初始化的,存放的是随机值(也有编译器会优化为存放0,比如VS2019就会将后续未赋值的空间初始化为0)

3.数组的访问

有了数组后,我们应该如何访问数组中的成员呢?

3.1 数组下标

答案是通过数组下标的方式来访问。

1
2
类型名 数组名[数组长度]; // 声明数组
数组名[数组下标]; // 下标访问数组成员

所谓数组下标,其实就是对应数据在数组中的位置。下标从开始,最大值是数组长度-1

长度为5的数组,下标范围是0到4;长度为10的数组,下标范围是0到9;

比如下面的数组,假设我们想访问第7位的数据,就需要用下标6访问;想访问第十位的数据,就要用下标9来访问;

1
2
3
int arr8[10] = {1,2,3,4,5,6,7,8,9,10};
int a1 = arr8[5]; // 访问第六位的数据
int a2 = arr8[9]; // 访问第十位的数据

而下标10就已经是越界访问了,因为下标10对应的是第十一位,而这份空间并不属于我们开辟的这个数组。

1
2
int arr8[10] = {1,2,3,4,5,6,7,8,9,10};
int a3 = arr8[10]; // 错误!下标10对应第十一位,越界了!

3.2 越界访问

所谓越界访问,就是访问了数组中不属于用户自己的空间。是一种BUG。

比如用户定义了一个长度为5的数组,却尝试访问第10个元素,就会出现越界访问。这是新手常犯的错误之一,下标控制也是C语言中比较麻烦的一环,大家需要注意

不同编译器对越界访问的检查也是不确定的,部分编译器能做到检测到越界访问后发出警告,比如VS2019。有些程序在运行到越界访问地方之时,会发生段错误(段错误即访问未定义和不属于用户自己的值)

3.3 通过指针访问数组

所有数组变量的本质,其实都是对应数据类型的一级指针

1
2
// arr9就是一个int*的一级指针
int arr9[10] = {1,2,3,4,5,6,7,8,9,10};

既然是指针,我们就可以通过指针的解引用方式来访问数组中的元素。实际上的[]下标访问,也会被编译器自动转成下面的指针访问形式来访问数组中的元素。

1
2
3
4
int a = (*arr9); 	// 等价于 arr9[0]
int b = (*(arr9+1)); // 等价于 arr9[1]
// 以此类推...
int c = (*(arr9+9)); // 等价于 arr9[9]

4.多维数组

数组本质上是指针,指针分为一级和二级,数组也有一维和多维

1
2
3
4
int arr10[10]; // 一维数组
int arr11[10][10]; // 二维数组,一个10x10的矩阵
int arr12[10][10][10]; // 三维数组
// 依此类推...

多维数组的访问方式,和一维数组是相同的,比如如下代码访问的就是数组中第二行第三列的数据

1
int k1 = arr11[1][2]; // 下标访问,第二行第三列

如果想用指针来访问多维数组,需要注意操作符的优先级问题,作为初学者,我们先用括号来括起来以避免优先级问题。这里可能有点绕,后续指针章节会讲解指针的寻址方式,到时候大家就能理解下面这行代码的深层含义了。

1
int k2 = *(*(arr11+1)+2); // 指针访问,第二行第三列