数组(array)用于在一段连续内存中保存多个同类型元素,通过下标访问各个元素。在 C 语言中,定义语法如下:
int numbers[10]; // 定义一个有 10 个 int 的数组下标从 0 开始
访问元素与定义使用相同形式:在方括号中写下标。C 语言数组下标从 0 开始;长度为 10 的数组,合法下标为 0 到 9。numbers[10] 已超出有效范围,属于越界访问。
int numbers[10];
numbers[0] = 10; // 第 1 个
numbers[1] = 20; // 第 2 个
numbers[2] = 30;
numbers[3] = 40;
numbers[4] = 50;
numbers[5] = 60;
numbers[6] = 70; // 第 7 个
/* 打印第 7 个数,它的下标是 6 */
printf("数组第 7 个数是 %d\n", numbers[6]);元素类型必须一致
数组在内存中占用连续空间,所有元素必须是同一类型(例如全部为 int 或全部为 double,不可混合)。按下标访问时,可通过首地址、下标与元素大小计算目标地址,因此随机访问的效率较高。
arr 为 5 个 int 连续排布,按下标可计算目标地址。声明与初始化
声明数组时,编译器会按给定长度分配内存。若未显式初始化,元素内容为不确定值,使用前应先赋值或初始化。常见写法如下:
int a[3] = {10, 20, 30}; // 依次填满
int b[] = {1, 2, 3, 4, 5}; // 省略数量,编译器按右边自动数
int c[5] = {1, 2}; // 部分初始化,其余自动补 0
int d[5] = {0}; // 将全部元素置为 0
/* 声明之后再整段赋 {} 不行,只能逐个元素赋值 */
a[0] = 99;初始化之后修改某个元素,与读取方式相同,通过下标赋值即可:a[2] = 77;
用循环遍历数组
有了下标之后,通常使用 for 循环按序访问元素,既可正序遍历,也可倒序遍历:
#include <stdio.h>
int main(void) {
int arr[5] = {2, 4, 8, 12, 16};
printf("正序:");
for (int i = 0; i < 5; i++) {
printf("%d ", arr[i]);
}
printf("\n倒序:");
for (int i = 4; i >= 0; i--) {
printf("%d ", arr[i]);
}
printf("\n");
int size = sizeof(arr) / sizeof(arr[0]); // 5
printf("数组里有 %d 个元素\n", size);
return 0;
}求元素个数常用 sizeof(arr) / sizeof(arr[0]):用数组总字节数除以单个元素字节数。该写法仅在数组所在作用域内有效;数组作为函数参数传递后不再适用(详见指针章节)。
数组越界:语言不设边界检查
int a[3] = {1, 2, 3};
a[3] = 100; // 越界,合法下标只到 2上述代码通常可以通过编译,运行时也可能不会立刻报错,但会向数组边界外的内存写入数据,可能破坏其他变量,属于未定义行为。与 Java 等会在运行时检测越界的语言不同,C 语言需要程序员自行保证下标合法。编写循环时建议使用 i < 长度,避免写成 i <= 长度。
二维数组:行与列
二维数组按行、列组织数据,使用 [行][列] 两个下标访问:
int grid[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
for (int r = 0; r < 3; r++) {
for (int c = 0; c < 4; c++) {
printf("%2d ", grid[r][c]);
}
printf("\n");
}在内存中,二维数组仍按行优先连续存储,两层方括号便于按行列理解。矩阵、棋盘、表格等场景常会使用二维数组。
下一章将介绍 C 语言中常用的字符数组,即字符串。