在 C语言中,数组是用于存储一组相同类型的元素。数组本质上是一块连续的内存空间,通过索引(下标)来访问其中的元素。
数组在 C语言编程中用途广泛,比如存储学生成绩、统计数据等。本文将从定义、声明、初始化、访问、常见操作以及注意事项等方面,全面讲解 C语言中的数组。
数组的基本概念
数组是一组有序的、类型相同的数据集合。它的核心特点是:
内存连续:数组中的元素在内存中紧密排列。
固定长度:数组一旦声明,大小不可改变。
索引访问:通过下标(从 0 开始)定位元素。
例如,一个存储 5 个整数的数组就像 5 个连续的“格子”,每个格子可以通过编号(0 到 4)来访问。
数组的声明和初始化
1) 声明数组
声明数组时,需要指定数据类型和数组大小。语法如下:
数据类型 数组名[大小];
示例:
int numbers[5]; // 声明一个能存 5 个整数的数组
这里,numbers 是一个数组名,5 是数组长度,int 是元素类型。
2) 初始化数组
声明数组后,可以立即初始化,也可以在之后赋值。C语言支持多种初始化方式:
int numbers[5] = {1, 2, 3, 4, 5}; // 完整初始化
int numbers[5] = {1, 2}; // 部分初始化,结果是 {1, 2, 0, 0, 0}
int numbers[] = {1, 2, 3, 4, 5}; // 省略长度,自动推断长度为 5
完整初始化:在声明时直接赋值。
部分初始化:未指定的元素自动填充为 0。
省略长度:编译器会根据初始值自动推断大小。
注意:如果声明时不初始化,数组元素的值是未定义的(可能是随机值),所以建议总是初始化。
访问与修改数组元素
数组通过下标访问元素,下标从 0 开始,到 大小 - 1 结束。语法如下:
数组名[下标]
示例代码:
#include
int main() {
int numbers[5] = {10, 20, 30, 40, 50};
printf("第一个元素:%d\n", numbers[0]); // 访问
numbers[2] = 35; // 修改
printf("修改后的第三个元素:%d\n", numbers[2]);
return 0;
}
输出结果:
第一个元素:10
修改后的第三个元素:35
在这个例子中,numbers[0] 访问第一个元素,numbers[2] 被修改为 35。
数组与循环结合使用
数组通常与循环一起使用,以便批量操作元素。以下是一个打印数组所有元素的例子:
#include
int main() {
int numbers[5] = {10, 20, 30, 40, 50};
int i;
for (i = 0; i < 5; i++) {
printf("numbers[%d] = %d\n", i, numbers[i]);
}
return 0;
}
输出结果:
numbers[0] = 10
numbers[1] = 20
numbers[2] = 30
numbers[3] = 40
numbers[4] = 50
for 循环的下标 i 从 0 到 4,正好覆盖数组的所有元素。
C语言多维数组
C语言支持多维数组,其中最常见的是二维数组,可以看作“表格”或“矩阵”。声明和初始化方式如下:
1) 声明与初始化
数据类型 数组名[行数][列数];
示例:
int matrix[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
这里,matrix 是一个 3 行 4 列的二维数组。
2) 访问二维数组
使用双重下标访问,第一个下标表示行,第二个表示列。例如:
#include
int main() {
int matrix[2][3] = {{1, 2, 3}, {4, 5, 6}};
printf("matrix[1][2] = %d\n", matrix[1][2]); // 访问第 2 行第 3 列
return 0;
}
输出结果:
matrix[1][2] = 6
3) 用嵌套循环遍历
二维数组通常需要嵌套循环来处理:
#include
int main() {
int matrix[2][3] = {{1, 2, 3}, {4, 5, 6}};
int i, j;
for (i = 0; i < 2; i++) {
for (j = 0; j < 3; j++) {
printf("%d ", matrix[i][j]);
}
printf("\n");
}
return 0;
}
输出结果:
1 2 3
4 5 6
外层循环控制行,内层循环控制列,完整遍历所有元素。
数组的常见操作
1) 计算数组元素之和
#include
int main() {
int numbers[5] = {1, 2, 3, 4, 5};
int sum = 0, i;
for (i = 0; i < 5; i++) {
sum += numbers[i];
}
printf("数组元素之和:%d\n", sum);
return 0;
}
输出结果:
数组元素之和:15
2) 查找最大值
#include
int main() {
int numbers[5] = {3, 8, 2, 9, 1};
int max = numbers[0], i;
for (i = 1; i < 5; i++) {
if (numbers[i] > max) {
max = numbers[i];
}
}
printf("最大值:%d\n", max);
return 0;
}
输出结果:
最大值:9
数组的内存本质
数组名在 C语言中是一个指向数组首地址的指针。以 numbers[5] 这个数组为例,numbers 等价于 &numbers[0]。这意味着可以用指针操作数组,但这是高级话题,感兴趣的读者可阅读《C语言数组指针(指向数组的指针)详解》一文。
内存连续性也带来一个问题:访问超出范围的下标(越界)会导致未定义行为,可能破坏其他数据或崩溃程序。
注意事项
下标越界:C语言不会检查数组边界,比如试图访问numbers[5]数组中下标为 5 的数据,即便程序能够正确运行,结果也是不可预测的。
大小固定:数组长度必须在编译时确定,不能动态调整(除非使用动态内存分配,如 malloc)。
初始化陷阱:未初始化的局部数组包含垃圾值,需手动清零或赋值。
总结
数组在 C语言程序中很常用,它可以存储多个类型相同的数据。
阅读完本文,相信你已经掌握了如何在 C 语言程序中正确使用数组。实际开发中,使用较多的是一维数组和二维数组,更高维次的数组则很少使用。
建议你在实践中多写代码,比如实现数组排序、反转等操作,以加深理解。数组虽简单,但它是学习指针和内存管理的基础,值得深入钻研。