C 语言数组全面复盘从一维到二维从语法到经典实战C 语言中数组是最基础也最常用的构造类型之一用来批量存储一组相同类型的数据。学完分支与循环后数组将我们的代码能力从处理单个数据提升到批量数据处理的层面。本文按照「语法规则 - 内存本质 - 实战练习」的逻辑完整复盘一维数组、二维数组、核心拓展知识点和两道经典算法题方便后续复习速查。一、一维数组从创建、初始化到内存本质1.1 概念与创建语法数组是一组相同类型元素的集合有两个核心特征所有元素类型统一数组一旦创建完成大小就固定不可修改。一维数组的标准创建语法type arr_name[常量值];type数组元素的类型如 int、char、double 等arr_name自定义数组名[ ] 内为数组大小指定元素个数示例intmath[20];// 存储20个int类型的成绩charch[8];// 存储8个char类型的字符注意在 C99 标准之前方括号内必须是整型常量表达式不能使用普通变量指定数组大小。1.2 三种初始化方式数组初始化使用大括号 {} 包裹初始值分为三种常见场景完全初始化初始值个数与数组大小完全一致intarr[5]{1,2,3,4,5};不完全初始化只给前几个元素赋值剩余元素系统默认初始化为 0intarr[6]{1};// 实际存储1, 0, 0, 0, 0, 0省略数组大小初始化时不写数组大小数组长度由初始值的个数自动决定intarr[]{1,2,3,4,5};// 数组大小自动为5补充数组本身有独立的类型例如 int arr[10]; 的完整类型是 int [10]大小不同的同类型数组属于不同的数组类型。1.3 下标访问规则C 语言中数组的下标从 0 开始计数。如果数组有 n 个元素合法下标范围是 0 ~ n-1。访问单个元素使用 下标引用操作符 []#includestdio.hintmain(){intarr[10]{1,2,3,4,5,6,7,8,9,10};printf(%d\n,arr[7]);// 访问下标为7的元素输出8printf(%d\n,arr[3]);// 访问下标为3的元素输出4return0;}遍历整个数组配合 for 循环生成所有下标即可#includestdio.hintmain(){intarr[10]{1,2,3,4,5,6,7,8,9,10};inti0;for(i0;i10;i){printf(%d ,arr[i]);}return0;}1.4 一维数组的内存本质一维数组的所有元素在内存中是连续存放的。随着下标增大元素的地址由低到高递增。以 int 数组为例每个 int 占 4 字节相邻两个元素的地址相差 4 字节#includestdio.hintmain(){intarr[10]{1,2,3,4,5,6,7,8,9,10};inti0;for(i0;i10;i){printf(arr[%d] %p\n,i,arr[i]);}return0;}1.5 经典坑点数组下标越界如果访问了超出 0 ~ n-1 范围的下标例如大小为 10 的数组访问 arr[10]属于数组下标越界是 C 语言的未定义行为。编译器不会强制报错但程序可能出现运行崩溃、输出随机垃圾值、数据被意外修改等不可预测的后果写代码时必须严格校验下标范围。二、二维数组行列逻辑与内存布局2.1 本质与创建语法二维数组的本质是「一维数组的数组」。例如 int arr[3][5];可以理解为一个长度为 3 的数组它的每个元素都是一个 int [5] 类型的一维数组。二维数组的标准创建语法type arr_name[行数][列数];第一个方括号对应行数第二个方括号对应列数。示例intarr[3][5];// 3行5列共15个int元素doubledata[2][8];// 2行8列共16个double元素2.2 二维数组的初始化平铺初始化按行顺序依次写入所有元素intarr[3][5]{1,2,3,4,5,2,3,4,5,6,3,4,5,6,7};按行初始化用大括号按行包裹结构更清晰intarr[3][5]{{1,2},{3,4},{5,6}};// 每行未赋值的元素默认补0省略行维度初始化时可以省略行数由编译器根据初始值自动推导但列数绝对不能省略intarr[][5]{1,2,3,4,5,6,7};// 自动推导为2行5列2.3 下标访问与遍历二维数组的行号、列号都从 0 开始计数访问单个元素的格式为 数组名[行号][列号]。完整遍历一个二维数组需要两层 for 循环外层控制行内层控制列#includestdio.hintmain(){intarr[3][5]{1,2,3,4,5,2,3,4,5,6,3,4,5,6,7};inti0,j0;// 遍历输出for(i0;i3;i){for(j0;j5;j){printf(%d ,arr[i][j]);}printf(\n);// 每行结束换行}return0;}2.4 二维数组的内存布局二维数组在内存中并不是 “表格状” 分开存储而是按行连续存放先存第 0 行的全部元素紧接着存第 1 行以此类推。整个二维数组占用一整块连续的内存空间跨行相邻的两个元素地址也是连续的。三、拓展补充sizeof 计算与变长数组3.1 sizeof 计算数组元素个数sizeof 可以计算类型或变量占用的字节数。直接对数组名使用 sizeof得到的是整个数组占用内存的总大小。由此可以推导出计算数组元素个数的通用公式intszsizeof(arr)/sizeof(arr[0]);用数组总字节数除以单个元素的字节数得到元素总数。这种写法的优势是当数组大小修改时代码无需手动修改数字能自动适配。3.2 易错点数组传参会退化数组作为函数参数传递时会退化为指向首元素的指针。因此在函数内部对数组参数使用 sizeof得到的是指针的大小32 位环境 4 字节64 位环境 8 字节而不是整个数组的总大小。如果函数内部需要数组长度必须把长度作为参数一起传入。3.3 C99 变长数组VLAC99 标准引入了变长数组Variable-length Array允许使用变量来指定数组的大小。含义说明「变长」指的是数组创建时大小可以由变量决定在程序运行时才能确定长度数组一旦创建完成大小就固定了不能再修改。语法约束变长数组不能在创建时进行初始化因为编译器在编译阶段无法确定数组长度无法校验初始化列表的元素数量。兼容性VS 系列编译器如 VS2022不支持 C99 变长数组特性GCC 等编译器支持。示例#includestdio.hintmain(){intn0;scanf(%d,n);intarr[n];// 变长数组大小由输入的n决定inti0;for(i0;in;i){scanf(%d,arr[i]);}return0;}四、经典实战练习4.1 练习 1字符从两端向中间汇聚题目编写代码演示多个字符从两端向中间逐渐显示的动画效果。实现思路定义两个字符数组一个存放最终要显示的真实内容另一个初始化为统一占位符如 #定义 left 和 right 两个下标分别标记字符串的左右两端循环向中间靠拢逐位替换占位符为真实字符每替换一次打印一次效果。参考代码#includestdio.h#includestring.h#includewindows.h// Sleep函数头文件Windows环境使用intmain(){chararr1[]welcome to bit...;chararr2[]#################;intleft0;intrightstrlen(arr1)-1;printf(%s\n,arr2);while(leftright){Sleep(1000);// 延时1000毫秒制造动画效果arr2[left]arr1[left];arr2[right]arr1[right];left;right--;printf(%s\n,arr2);}return0;}4.2 练习 2二分查找折半查找题目给定一个升序的整型数组查找指定的数字。找到则打印对应下标找不到则提示 “找不到”。前提条件二分查找只能用于有序数组无序数组无法使用。核心思路每次取区间中间的元素和目标值比较一次排除一半的元素查找效率远高于逐个遍历。核心变量left查找区间的左边界下标初始为 0right查找区间的右边界下标初始为元素个数 - 1mid当前区间的中间元素下标参考代码#includestdio.hintmain(){intarr[]{1,2,3,4,5,6,7,8,9,10};intkey7;// 要查找的目标值intleft0;intrightsizeof(arr)/sizeof(arr[0])-1;intmid0;intfind0;// 标记是否找到while(leftright){// 优化写法避免leftright过大导致整数溢出midleft(right-left)/2;if(arr[mid]key){rightmid-1;// 目标在左半区缩小右边界}elseif(arr[mid]key){leftmid1;// 目标在右半区缩小左边界}else{find1;break;// 找到退出循环}}if(find1)printf(找到了下标是%d\n,mid);elseprintf(找不到\n);return0;}优化说明mid (left right) / 2 在数值很大时可能发生整数溢出mid left (right - left) / 2 计算结果一致但完全规避了溢出风险是工业级代码的标准写法。总结数组是 C 语言批量数据处理的基础核心要点可以归纳为三点下标从 0 开始必须严格避免下标越界无论是一维还是二维数组元素在内存中都是连续存放的数组作为函数参数传递时会退化为指针函数内无法直接求得数组总长度。掌握基础语法后通过二分查找这类经典算法练习可以加深对数组下标的理解也为后续学习指针、字符串、数据结构打下扎实基础。