C语言数组详解:创建初始化、内存存储与传参陷阱
本文深入解析C语言一维及二维数组的创建与初始化规范,特别是字符数组的 \`\0\` 结尾机制。通过对比不同方式定义字符串的差异,揭示数组名在 sizeof 和 & 操作下的特殊含义,并详细剖析函数传参时数组退化为指针导致的长度计算错误,最后提供带状态标志的冒泡排序正确实现方案。
1. 一维数组的创建和初始化
第1步:创建数组并规范语法
数组是相同类型元素的集合。创建时需指定元素类型和常量大小(C99之前):
// type_t 为元素类型,const_n 为常量表达式
type_t arr_name[const_n];
int arr1[10]; // 合法
char arr3[10];
// int count = 10;
// int arr2[count]; // C89标准不支持,易引发歧义,建议使用常量或宏
第2步:初始化并注意字符数组的结束符
初始化可通过直接赋值确定大小,不指定大小时由内容决定:
int arr[] = {1, 2, 3}; // 自动推断大小为3
char arr_str[] = "abcdef"; // 隐式包含结尾 ' ',实际占用7字节
仔细区分以下五种字符串/字符数组的定义差异:
char arr1[] = "abc"; // 包含' ', 长度4
char arr2[3] = {'a','b','c'}; // 无' ', 打印将导致乱码
char arr3[] = {'a','b','c'}; // 同上
char arr4[4] = {'a','b','c'}; // 末尾未赋值为' '(可能为0),但逻辑上不应依赖
char arr5[] = {'a','b','c',' '}; // 显式包含' ', 长度4
推荐使用双引号 char arr1[] = "abc"; 的形式,编译器会自动处理结尾标识。
第3步:使用下标访问与内存连续存放验证
数组下标从 0 开始。可通过指针递增观察内存地址规律:
int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int *p = &arr[0];
for (int i = 0; i < 10; i++) {
printf("&arr[%d]=%p <==> %p\n", i, &arr[i], p++);
}
执行结果表明,随着下标增加,内存地址连续递增(每个 int 占 4 字节)。
2. 二维数组的创建和使用
第4步:创建并初始化二维数组
二维数组可看作“行”与“列”的组合。初始化时若省略行数,列数必须指定:
int arr[][4] = {{1, 2}, {3, 4}}; // 自动推断为2行
int arr1[][5] = {1, 2, 3, 4, 5, 6}; // 不完全初始化,补充全零
第5步:遍历二维数组并观察内存连续性
二维数组在内存中依然是连续存放的:
int arr[3][5] = {{1, 2},{3, 4},{5, 6}};
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 5; j++) {
printf("&arr[%d][%d]=%p\n", i, j, &arr[i][j]);
}
}
&arr[0][3] 与 &arr[1][0] 地址相连。
3. 数组越界风险与控制
C语言不进行越界检查,程序员需自行保证范围限制(0 到 n-1)。当循环条件写成 <= 时极易触发越界:
int arr[10] = {1, ..., 10};
for(int i=0; i<=10; i++) { // i=10 时为非法访问
printf("%d\n", arr[i]);
}
4. 数组作为函数参数的核心陷阱
第6步:理解数组传参时的退化现象
常见的冒泡排序实现错误在于函数内调用 sizeof(arr):
void bubble_sort_err(int arr[]) {
// 此时 arr 退化为指针!sizeof(arr) 等于指针大小(如4),非数组总大小
int sz = sizeof(arr)/sizeof(arr[0]);
}
通过单步调试可见,虽然主函数传入了10个元素,但进入函数后数组被视为首元素地址(指针),长度为1而非10,导致排序失效。
第7步:掌握数组名的两个特例
sizeof(数组名):表示整个数组的大小。&数组名:表示整个数组的地址。- 除此之外,所有数组名均代表首元素地址。
验证如下:
printf("%p\n", arr); // 首元素地址
printf("%p\n", &arr); // 数组地址(数值同,但类型意义不同)
第8步:修正冒泡排序实现
在调用者计算好元素个数 sz 并传给函数:
void bubble_sort(int* arr, int sz) {
int i, j, flag;
for(i = 0; i < sz - 1; i++) {
flag = 1;
for(j = 0; j < sz - 1 - i; j++) {
if(arr[j] > arr[j+1]) {
int tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
flag = 0;
}
}
if(flag == 1) break; // 提前终止优化
}
}
int main() {
int arr[] = {3, 1, 2, 4, 5, 6, 8, 9, 7, 10};
int sz = sizeof(arr)/sizeof(arr[0]);
bubble_sort(arr, sz);
// ... 输出结果 ...
}
总结
以上就是C语言数组的详细内容,更多关于C语言数组的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













