C 数组
C 数组
在 C 语言中,数组(Array) 是一种用于存储相同类型数据的集合结构。它是程序中最基础、最常用的复合数据类型之一。
掌握数组的操作是理解更高级数据结构(如字符串、指针、结构体)的基础。
一、学习目标 🎯
- 掌握一维数组的定义、初始化和访问方式。
- 理解数组在内存中的连续性特点与索引越界的危害。
- 能够使用数组实现简单的算法,如查找、排序等。
二、核心重点 🔑
- C 中数组是一段连续的内存空间,所有元素类型必须一致。
- 数组下标从 0 开始;访问时注意防止索引越界(否则可能引发未定义行为)。
- 数组名本质上是一个指向首元素的常量指针。
三、详细讲解
✅ 1. 一维数组的定义与初始化
语法:
类型 数组名[元素个数];
示例:
#include <stdio.h>
int main(void) {
int numbers[5]; // 定义一个长度为 5 的整型数组
numbers[0] = 10;
numbers[1] = 20;
numbers[2] = 30;
numbers[3] = 40;
numbers[4] = 50;
printf("第三个元素是:%d\n", numbers[2]);
return 0;
}
⚠️ 注意事项:
- 数组大小必须是编译时常量(C99 后允许变长数组,但不推荐);
- 不能直接赋值整个数组,只能逐个元素赋值或使用循环。
✅ 2. 初始化数组的不同方式
(1)声明时初始化全部元素:
int nums[] = {1, 2, 3, 4, 5}; // 自动推断大小为 5
(2)指定部分元素初始化:
int nums[5] = {1, 2}; // 剩余位置自动填充为 0
(3)使用 for
循环动态赋值:
int arr[10];
for (int i = 0; i < 10; i++) {
arr[i] = i * 2;
}
✅ 3. 数组的遍历与访问
使用 for
或 while
循环可以方便地遍历数组。
示例:计算数组总和
#include <stdio.h>
int main(void) {
int scores[] = {85, 90, 78, 92, 88};
int length = sizeof(scores) / sizeof(scores[0]); // 计算元素个数
int sum = 0;
for (int i = 0; i < length; i++) {
sum += scores[i];
}
printf("总成绩:%d\n", sum);
return 0;
}
⚠️ 注意事项:
- 使用
sizeof(array) / sizeof(array[0])
可以获取数组长度;- 不适用于作为函数参数传入的数组(此时会退化为指针)。
✅ 4. 多维数组 —— 二维数组为例
语法:
类型 数组名[行数][列数];
示例:打印一个 3x3 的矩阵
#include <stdio.h>
int main(void) {
int matrix[3][3] = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
printf("%d ", matrix[i][j]);
}
printf("\n");
}
return 0;
}
⚠️ 注意事项:
- 二维数组本质是“数组的数组”;
- 所有元素在内存中仍然是按行连续存储的。
✅ 5. 数组与函数的交互
数组不能直接作为函数参数传递,而是会退化为指针。
示例:将数组传入函数求最大值
#include <stdio.h>
int findMax(int arr[], int size) {
int max = arr[0];
for (int i = 1; i < size; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
return max;
}
int main(void) {
int nums[] = {10, 25, 7, 45, 30};
int size = sizeof(nums) / sizeof(nums[0]);
int result = findMax(nums, size);
printf("最大值是:%d\n", result);
return 0;
}
⚠️ 注意事项:
- 函数无法通过
sizeof(arr)
获取数组长度;- 必须手动传递数组长度。
✅ 6. 数组与指针的关系(进阶)
数组名本质上是一个指向数组第一个元素的指针。
示例:
#include <stdio.h>
int main(void) {
int arr[] = {10, 20, 30, 40, 50};
printf("arr = %p\n", (void*)arr); // 指向 arr[0]
printf("&arr[0] = %p\n", (void*)&arr[0]); // 同上
printf("*(arr + 2) = %d\n", *(arr + 2)); // 输出 30
return 0;
}
⚠️ 注意事项:
arr
是常量指针,不能进行arr++
;- 使用指针访问数组效率更高,但也更容易出错。
四、常见陷阱与避坑指南 ⚠️
陷阱 | 描述 | 解决方案 |
---|---|---|
❗数组越界访问 | 导致未定义行为 | 用循环控制边界 |
❗未初始化数组 | 默认值不确定 | 显式初始化或使用 memset() |
❗数组名作为参数传递 | 退化为指针 | 手动传递数组长度 |
❗误认为数组可以整体赋值 | 实际需逐个复制 | 使用 memcpy() 或循环赋值 |
五、拓展练习 🧩
🧩 练习题 1:求数组中的最小值
编写一个函数 findMin(int arr[], int size)
,返回数组中的最小值。
🧩 练习题 2:数组逆序输出
输入一个整型数组,将其内容逆序后输出。
提示:可用双指针法或循环交换。
🧩 练习题 3:冒泡排序实现
写一个函数实现冒泡排序算法,对数组进行升序排列,并在主函数中测试。
🧩 练习题 4:统计数字出现次数
给定一个包含 0~9 的整数数组,统计每个数字出现的次数,并输出结果。
示例:
输入:{1, 2, 2, 3, 3, 3, 4}
输出:
1 出现了 1 次
2 出现了 2 次
...
六、实战建议总结
场景 | 推荐做法 |
---|---|
静态数据存储 | 使用固定大小数组 |
动态扩容需求 | 使用动态内存分配(malloc /calloc ) |
提高访问效率 | 使用指针代替下标访问 |
避免越界访问 | 使用循环控制边界 |
封装操作逻辑 | 将常用功能封装成函数(如排序、查找) |
恭喜你完成了《C 数组》这一章的学习!
你现在掌握了如何使用数组来高效地组织和处理批量数据,这是构建复杂程序的重要一步。
✅ 下一章推荐学习内容(任选其一):
- 《C 字符串处理:char 数组与标准库函数》
- 《C 指针详解:地址、取值、运算与数组访问》
- 《C 结构体与联合体:自定义复合数据类型》
- 《C 内存管理:栈、堆、静态区与 malloc/free》
你想继续学哪个?我来为你定制下一章内容 👇