1.一维数组
(1)数组的创建
数组,是一组相同类型的元素的集合。
一维数组的创建方式为
type_t arr_name [const_n]
//type_t 数组的元素类型
//arr_name 数组名
//const_n 是一个常量表达式,用来指定数组的大小
在C99标准之前,数组的大小只能是常量表达式
C99标准中,引入了变长数组的概念,使得数组在创建时可以引入变量,但是这样的数组不能够初始化。
而像VS2019,VS2022这样的IDE,就不支持C99中的变长数组。
int arr[n];
//数组大小是由一个变量n来确定,为变长数组
//若是由局部变量定义,这样的局部变量或者数组是存放在栈区上
//栈区上的数组,如果不初始化,默认是随机值
(2)数组的初始化
数组的初始化是指在创建数组时,给数组的元素赋予一些合适的初始值。
初始化又分为完全初始化和不完全初始化:
int arr[10] = {1,2,3,4,5,6,7,8,9,10};//完全初始化,数组中的每个元素都赋初值
int arr[10] = {1,2,3,4};//不完全初始化,部分元素赋初值
进行不完全初始化时,剩余的为初始化元素默认都是0;
int arr[] = {1,2,3};
//不指定数组的空间大小时,必须对数组进行初始化
//此时数组空间大小由初始化元素的个数确定
对于字符数组:不同的初始化方式会由不同的效果
char ch[] = {'a', 'b', 'c'};//数组长度为3
char ch{} = "abc";//数组长度为4
直接放字符串进去,会在字符串的末尾多出一个‘\0’,此时数组长度为4;以单个字符的形式进行初始化的时候,不会放入‘\0’,此时数组长度为3。
还有一种初始化方式是使用对应字符的ASCII码值,也可以达到相同的效果。
char ch[] = {'a', 98, 'c'};
(3)数组的使用
对于数组的使用,其实就是利用“[]”——下标引用操作符,它其实就是数组访问的操作符。
2.一维数组在内存中的存储
一维数组在内存中是连续存放的,并且随着下标的增长,地址也在增长,说明数组元素在内存中是由低地址到高地址连续存放的。
3.二维数组
(1)二维数组的创建
int arr[3][4] 表示创建一个三行四列的数组,第一个参数表示行数,第二个参数表示列数。
也可以理解为创建一个三行的数组,每行存放四个元素。
(2)二维数组的初始化
二维数组初始化也可分为完全初始化和不完全初始化,不完全初始化时会自动补0。
二维数组的行和列也都是从0开始的。
在创建二维数组时,行可以省略,但是列不能省略。
行数可以通过初始化情况来判断。
4.二维数组在内存中的存储
二维数组在内存中也是连续存放的,并且也是从低地址到高地址存放。
二维数组可以理解为是【一维数组】的数组,把【一维数组】当作整体作为一个数组元素进行存储。(理解)
5.数组越界
数组的下标是有范围限制的,规定数组下标从0开始,若数组含有n个元素,那么数组最后一个元素的下标即为n-1.
所以数组的下标如果小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。
C语言本身不做数组越界的检查,编译器也不一定报错,但是编译器不报错,不代表程序就是正确的。
在使用数组时,最好自己做好越界检查。
6.数组作为函数参数
写代码的时候,往往会将数组作为函数的参数进行调用。
数组在作为参数进行传参的时候,传递的是地址,是数组首个元素的地址。
数组名即为数组首元素的地址。(通常情况下)
但是有两个例外情况:
1.sizeof(数组名),数组名单独放在sizeof()操作符的内部,这里的数组名表示的是整个数组,sizeof()可以通过这种方式求出整个数组所占的空间的大小。
2.&数组名,这里的数组名也表示整个数组,这里取出的是整个数组的地址。
除了这两种情况以外,遇到的数组名单独出现的情况,都表示数组首元素的地址。
情况2的演示: