当需要定义多个相同的变量或者描述同一类相同的东西时,可以使用数组来进行定义。
一维数组
一维数组中的“一维”是相对与“二维”来说的,主要用来描述线性化的数据序列。
声明
定义:
数据类型名 变量名[正整数];
需要注意的是,数组占用内存的数量:
#include <stdio.h>
#include <Windows.h>
int main()
{
int array[10];
printf("sizeof(array) = %d\n", sizeof(array));
printf("sizeof(int[10]) = %d\n", sizeof(int[10]));
printf("sizeof(array[0]) = %d\n", sizeof(array[0]));
system("pause");
return 0;
}
结果为:
sizeof(array) = 40
sizeof(int[10]) = 40
sizeof(array[0]) = 4
从上面我们可以看出,sizeof(array) 计算得到的是以 array[0] 开头的 int[10] 的内存数目。
存储
- 一维数组在内存中是一段连续的存储区域
- 一维数组访问时有三个访问要素:起始位置,单个元素的字节长,范围
- 成员访问用符号 [] 实现,下表从 0 开始
初始化
格式举例:
int array[10] = {0,1,2,3,4,5,6,7,8,9};
在不同的条件下对一维数组进行初始化,会出现不同的结果:
- 不初始化:对数组成员进行打印,会出现随机值
- 全初始化:对应初始化
- 部分初始化:未初始化部分自动为 0
- 满初始化:数组范围限定了初始化的范围,超出范围的初始化表示对未知的内存赋值
- 不指定大小初始化:会按照初始化值个数进行数组构建
另外要注意:构造类型只能在声明的时候进行初始化,否则就只能在声明完成后分别对单个元素赋值。
变长数组
C99 为了增加 C 语言的灵活性,提供了变长数组(Variable Length Array,VLA)。使用举例:
#include <stdio.h>
int main()
{
int size;
scanf("%d", &size);
int array[size]; //变长数组不能被初始化 = {1,2,3,4,5};
printf("sizeof(array) = %d\n", sizeof(array));
size = 15; //此时再改变 size 的值, 数组的大小, 不再发生改变
printf("sizeof(array) = %d\n", sizeof(array));
return 0;
}
需要注意的是:边长数组是指用整型变量或表达式声明或定义的数组,并不是说数组的长度会随时发生变化,边长数组在其生存周期内的长度是固定的。程序结果可以自行探究。
二维数组
二维数组是相对于一维数组来说明的,如果说一维数组说明的是线性的元素集合,那么二维数组说明的就是阵列式的元素集合,只不过二维数组的每一行都是一个一维数组。
声明
数据类型 变量名[正整数][正整数];
可以通过 sizeof 函数查看二维数组的字节长度,如下:
#include <stdio.h>
#include <Windows.h>
int main()
{
int arr[3][4];
printf("sizeof(arr) = %d\n", sizeof(arr));
printf("sizeof(arr[0]) = %d\n", sizeof(arr[0]));
printf("sizeof(arr[0][0]) = %d\n",sizeof(arr[0][0]));
system("pause");
return 0;
}
结果如下:
sizeof(arr) = 48
sizeof(arr[0]) = 16
sizeof(arr[0][0]) = 4
从图中可以看出,sizeof(arr) 指代的是整个二维数组的字节长度,sizeof(arr[0]) 指代的是第一个一维数组的字节长度,sizeof(arr[0][0]) 指代的才是单个元素的字节长度。
存储
之前我们说一维数组的存储是内存中连续的一段长度,对于二维数组的存储我们可以打印单个元素的地址来看看:
#include <stdio.h>
#include <Windows.h>
int main()
{
int arr[3][4];
for (int i = 0; i < 3; i++)
for (int j = 0; j < 4; j++)
printf("The address of array[%d][%d] is %x\n", i, j, &arr[i][j]);
system("pause");
return 0;
}
执行结果为:
The address of array[0][0] is 6f9efb48
The address of array[0][1] is 6f9efb4c
The address of array[0][2] is 6f9efb50
The address of array[0][3] is 6f9efb54
The address of array[1][0] is 6f9efb58
The address of array[1][1] is 6f9efb5c
The address of array[1][2] is 6f9efb60
The address of array[1][3] is 6f9efb64
The address of array[2][0] is 6f9efb68
The address of array[2][1] is 6f9efb6c
The address of array[2][2] is 6f9efb70
The address of array[2][3] is 6f9efb74
从结果来看,二维数组在内存中的存储也是线性连续的,并且是是按行存储的。
初始化
初始化举例:
int array[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12}; //全局
int array[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}}; //行
二维数组的初始化和一维数组类似,也有几种不同的类型:
- 不初始化:打印数组成员值时会出现随机值
- 全初始化:按照行的顺序分别初始化
- 部分初始化(全局):按照行的顺序对全局前端的成员进行初始化,剩余的自动初始化为 0
- 部分初始化(行):每行的前端成员进行初始化,剩余的自动初始化为 0
- 满初始化:同一维数组类似,超出二维数组范围的成员赋值意味着对未知的内存位置赋值
- 不指定行大小初始化:根据初始化值的个数自动确定行数
数组名的含义
数组名是数组的唯一标识符,即表示一种构造数据类型的大小,也表示组中成员的首地址,组中其它成员的地址都是根据首地址加上相应的元素个数与数据类型的乘积得到的。