相同类型
数据按一定顺序
排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理。数组的特点:
连续的空间
。占据的空间的大小,取决于数组的长度和数组中元素的类型。长度一旦确定,就不能修改
。按照数组维度分:
按照元素的数据类型分:
数组通过变量名后加方括号表示,方括号里面是数组可以容纳的成员数量(即长度)。
int arr[10]; //数组 arr ,里面包含10个成员,每个成员都是 int 类型
#define NUM 10
int arr1[NUM];
注意,声明数组时,必须给出数组的大小。
数组名[下标]
下标从0开始
,用“int arr[10];”定义数组,则最大下标值为9
,不存在数组元素arr[10]。arr[0] = 13; //对该位置数组元素进行赋值
int score = arr[0]; //调用此位置的元素值
数组角标越界:
假设数组有n个元素,如果使用的数组的下标小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。
C语言不做数组下标越界的检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就是正确!
int scores[20];
scores[20] = 51;
说明:数组 scores 只有20个成员,因此 scores[20] 这个位置是不存在的。但是,引用这个位置并不会报错。赋值操作会导致紧跟在 scores 后面的那块内存区域被赋值(这实际是其它变量的区域),因此不知不觉就更改了其它变量的值。这很容易引发错误,而且难以发现。
数组的字节长度
sizeof 运算符会返回整个数组的字节长度。
int arr[10];
printf("数组的字节长度为:%zd\n",sizeof(arr)); //40(一个int占4个字节)
数组的长度
在定义数组时,需要指定数组中元素的个数,方括号中的常量表达式用来表示元素的个数,即数组长度。
由于数组成员都是同一个类型,每个成员的字节长度都是一样的,所以数组整体的字节长度除以某个数组元素的字节长度,就可以得到数组的成员数量。
//数组中元素的个数:
int arrLen = sizeof(arr) / sizeof(arr[0]);
int a[10];
printf("数组的字节长度为:%zu\n", sizeof(a)); // 40
printf("数组每个元素的字节长度为:%zu\n", sizeof(int)); // 4
printf("数组的长度为:%zu\n", sizeof(a) / sizeof(int)); // 10
复习: sizeof 返回值的数据类型是
size_t
,所以 sizeof(a) / sizeof(a[0]) 的数据类型也是size_t 。在 printf() 里面的占位符,要用 %zd 或 %zu 。
注意:数组一旦声明/定义了,其长度就固定了,不能动态变化。
将数组中的每个元素分别获取出来,就是遍历
。for循环与数组的遍历是绝配。
举例:声明长度为10的int类型数组,给数组元素依次赋值为0,1,2,3,4,5,6,7,8,9,并遍历数组所有元素
int main() {
int arr[10];
//给数组中的每个元素赋值
for (int i = 0; i < sizeof(arr)/sizeof(int); i++) {
//对数组元素arr[0]~arr[9]赋值
arr[i] = i;
}
//遍历数组中的元素
printf("遍历数组中的元素:\n");
for (int i = 0; i < sizeof(arr)/sizeof(int); i++) {
//输出arr[0]~arr[9]共10个数组元素
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
定义方式2:(定义方式1在2.1节讲的)
数组可以在声明时,使用大括号,同时对每一个成员赋值。
int arr[5] = {
22, 37, 90, 48, 95};
变形形式1:
C 语言允许省略方括号里面的数组成员数量,这时根据大括号里面的值的数量,自动确定数组的长度。
int arr[3] = {
10,20,30};
// 等同于
int arr[] = {
10,20,30}; //数组 arr 的长度,将根据大括号里面的值的数量,确定为 3
变形形式2:
对数组部分元素赋初值:如果大括号里面的值,少于数组的成员数量,那么未赋值的成员自动初始化为 0 。
int arr[5] = {
10, 20, 30};
// 等同于
int arr[5] = {
10,20,30, 0, 0};
变形方式3
:
将整个数组的每一个成员都设置为零,最简单的方式如下
int a[100] = {
0};
错误方式:
使用大括号赋值时,大括号里面的值不能多于数组的长度,否则编译时会报错。
int arr[3] = {
1,2,3,4}; // 报错
**定义方式3:**数组初始化时,可以指定为哪些位置的成员赋值。
int arr[15] = {
[2] = 10, [5] = 20, [14] = 30}; //非角标2、5、14的位置自动赋值为0
//等同于
int arr[15] = {
[5] = 20, [14] = 30, [2] = 10}; //指定位置的赋值可以不按角标从小到大的顺序
变形形式1:
指定位置的赋值与顺序赋值,可以结合使用。
int arr[15] = {
1, [5] = 10, 11, [10] = 20, 21}; //角标0、5、6、10、11的位置被赋值
变形形式2:
省略成员数量时,如果同时采用指定位置的赋值,那么数组长度将是最大的指定位置再加1。
int arr[] = {
[2] = 6, [9] = 12}; //此时数组的长度是10
针对于如下代码:
int a[5] = {
1,2,3,4,5};
对应的内存结构:
说明:
1)数组名,记录该数组的首地址 ,即 a[0]的地址。
2)数组的各个元素是连续分布的, 假如 a[0] 地址是0x1122,则a[1]地址= a[0]的地址+int字节数(4)
= 0x1122