20-c语言数组
本文最后更新于 2026-02-27,文章内容可能已经过时。
C语言数组是连续存储相同类型数据的结构,数组名本质是首元素地址(常量指针),因此数组操作与指针操作等价(如
arr[i]等价于*(arr + i));指针遍历数组(如for(int *p=arr; p<arr+n; p++))比下标法更高效,是C语言高效处理数据的核心机制,掌握此关系可避免常见误区(如数组名不可赋值),并为二维数组等高级操作奠定基础。
一、数组的基本概念
数组是C语言中存储多个相同类型数据的核心数据结构,其本质是"相同数据类型 + 连续内存地址"的集合。数组具有以下核心特点:
- 数据类型统一:所有元素必须是同一类型(如int、float、char等)
- 内存地址连续:相邻元素的内存地址相差一个数据类型的大小(如int数组相邻元素差4字节)
- 长度固定:数组长度一旦定义无法修改,需提前规划存储容量
通俗理解:数组就像一排整齐的"储物箱",每个箱子类型相同(比如都是int型),有唯一编号(下标),能快速存放和查找数据。
二、一维数组的定义与初始化
1. 定义格式
类型 数组名[长度];
- 类型:支持所有C语言基础数据类型(int、char、float等)
- 数组名:变量名,遵循命名规则(字母/数字/下划线组成,非数字开头、非关键字、区分大小写)
- 长度:表示数组可存储的元素个数
2. 初始化方式
// 全部初始化
int a[5] = {1, 2, 3, 4, 5};
// 部分初始化(剩余元素自动初始化为0)
int b[5] = {1, 2}; // b[0]=1, b[1]=2, b[2-4]=0
// 不指定长度(编译器自动确定)
int c[] = {1, 2, 3, 4, 5}; // 等同于 int c[5] = {1,2,3,4,5};
3. 空间大小计算
数组总空间大小 = 单个元素类型大小 × 数组长度
int a[10];
printf("数组总空间: %zu字节\n", sizeof(a)); // 40字节(int占4字节)
printf("单个元素空间: %zu字节\n", sizeof(a[0])); // 4字节
三、数组与指针的关系
1. 数组名的本质
在C语言中,数组名本身代表数组首元素的地址,是一个常量,不能被修改。
int arr[5] = {1, 2, 3, 4, 5};
printf("%p\n", arr); // 数组首地址
printf("%p\n", &arr[0]); // 数组首地址,与arr等价
重要区别:数组名是常量,不能被赋值;指针变量是变量,可以被修改。
2. 指针指向数组
int *p = arr; // p指向数组arr的首元素
int *q = &arr[0]; // 等价于 p = arr
四、数组的遍历与操作
1. 三种遍历数组的方式(速度对比)
| 遍历方式 | 代码示例 | 说明 |
|---|---|---|
| 下标法 | for (int i=0; i<n; i++) printf("%d", arr[i]); | 中规中矩,适合新手 |
| 数组名指针法 | for (int i=0; i<n; i++) printf("%d", *(arr + i)); | 聪明的"理科生" |
| 指针变量法 | for (int *p=arr; p<arr+n; p++) printf("%d", *p); | 速度担当的"特长生" |
实测结论:指针变量法比下标法快30%+,因为少了
arr[i]转*(arr+i)的编译步骤。
2. 指针操作数组的示例
#include <stdio.h>
int main() {
int arr[5] = {1, 2, 3, 4, 5};
int *p = arr; // 指针指向数组首元素
// 指针遍历数组
for (int i = 0; i < 5; i++) {
printf("%d ", *(p + i)); // 等价于 arr[i]
}
// 指针递增遍历
for (int *p = arr; p < arr + 5; p++) {
printf("%d ", *p);
}
return 0;
}
3. 指针与数组的等价性
// 以下写法等价
arr[i] == *(arr + i)
i[arr] == *(i + arr) // 虽然语法合法,但不推荐使用
五、二维数组的操作
1. 二维数组的内存布局
二维数组在内存中是连续存储的,可以看作"数组的数组"。
int arr[3][4]; // 3行4列
2. 指向二维数组的指针
int arr[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
// 指向二维数组的指针
int (*p)[4] = arr; // p指向一个包含4个int的数组
// 访问元素
printf("%d\n", *(*(p + 1) + 2)); // 访问arr[1][2],输出7
3. 二维数组的遍历
// 通过指针遍历二维数组
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
printf("%d ", *(*(p + i) + j));
}
}
六、常见误区与避坑指南
1. 数组名是常量,不能被赋值
// 错误示例:数组名是常量,不能被赋值
int a[10];
for (int *p = a; a < a + 10; a++) { // 错误!a是常量
printf("%d ", *a);
}
2. 函数参数传递数组
当数组作为函数参数传递时,数组名会退化为指针:
void modifyArray(int arr[]) {
arr[0] = 100; // 修改的是原数组
}
int main() {
int a[5] = {1, 2, 3, 4, 5};
modifyArray(a);
printf("%d", a[0]); // 输出100,原数组被修改
}
3. 字符串处理的特殊性
char str[10] = "hello"; // 字符串以'\0'结尾
printf("%s", str); // 输出hello
注意:字符串必须以'\0'结尾,输入字符串时不能包含空格(使用scanf时)。
4. 二维数组指针声明
// 正确声明指向二维数组的指针
int (*p)[4] = arr; // p指向包含4个int的数组
// 错误声明
int *p[4] = arr; // 这是数组指针,不是指向二维数组的指针
七、总结
- 数组是连续内存的集合,数组名代表首元素地址(常量)
- 指针可以指向数组,通过指针操作数组是C语言的精髓
- 数组与指针的访问方式等价:
arr[i]≡*(arr + i) - 指针遍历数组比下标法更快,但需注意指针的边界
- 二维数组可以看作"数组的数组",指针操作需特别注意类型
核心理解:数组名是常量,指针是变量。指针的算术运算使我们能够高效地遍历和操作数组,这是C语言强大和灵活的关键所在。
掌握数组与指针的关系,是深入学习C语言、理解内存操作、实现高效数据处理的基础。通过多练习指针与数组的结合使用,你会逐渐体会到C语言的精妙之处。
- 感谢你赐予我前进的力量
赞赏者名单
因为你们的支持让我意识到写文章的价值🙏
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 软件从业者Hort
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果

