【C语言入门5】数组 1.数组的概念数组是一组相同类型元素的集合从这个概念中我们就可以发现2个有价值的信息数组中存放的是1个或者多个数据但是数组元素个数不能为0。数组中存放的多个数据类型是相同的。数组分为一维和多維数组多維数组一般比较多见的是二维数组。2.一维数组的创建和初始化2.1 数组创建一维数组创建的基本语法如下type arr_name[常量值]| | |类型 名字 数组的大小存放在数组的元素称为数组的元素数组在创建的时候可以指定数组大小和数组的元素类型。比如我们现在想存储某个班级的20个人的数学成绩那我们就可以创建一个数组如下int math[20];其他类型的数组也是同理可得只要将类型和大小根据你的需要进行制定。2.2数组的初始化数组的初始化跟我们给变量进行初始化是同一个道理。只是数组的初始化一般使用大括号将数据放在大括号中。//完全初始化 int arr[5] {1,2,3,4,5}; //不完全初始化 int arr2[5] {1,2};//第一个元素初始化为1,第二个元素初始化为2剩余的元素默认为0 //错误的初始化 - 初始化项多于我们给数组制定的值 int arr3[3] {1,2,3,4}; //数组的大小是可以省略的 int arr4[] {1,2,3,4,5};//由初始化的值来决定数量和下面的那一行代码是同一效果 int arr5[5] { 1,2,3,4,5 };2.3数组的类型数组也是有类型的数组算是一种自定义类型去掉数组名留下的就是数组的类型。int main() { int arr[10];//arr是数组 //int是数组元素的类型 //int[10]是数组的类型 printf(%zu\n,sizeof(arr));//结果是40因为int个整型是4,10个就是40 printf(%ze\n,sizeof(int[10]));//40 int arr2[5];//int[5] printf(%zu\n, sizeof(int[5]));//结果是20它的数组类型就不会和int[10]一样 return 0; }3.一维数组的使用一维数组可以存放数据存放数据的目的是对数据的操作。3.1 数组下标C语言规定数组是有下标的下标是从0开始如果数组有n个元素那最后一个元素的下标就是n-1下标就相当于数组元素的编号。如下int arr[10] {1,2,3,4,5,6,7,8,9,10};数组元素和下标在C语言中数组的访问提供了一个操作符[ ]这个操作符叫下标引用操作符。有了下标引用操作符我们就可以轻松访问数组元素了如下#Includestdio.h int main() { int arr[10] {1,2,3,4,5,6,7,8,9,10}; printf(%d\n,arr[7]);//结果为8 printf(%d\n,arr[0]);//结果为1 arr[6] 70;//通过赋值修改数组中的某个值 printf(%d\n, arr[6]); return 0; }然后我们还可以借助for循环将每个数组元素都打印出来如下所示#includestdio.h int main() { int arr[10] {1,2,3,4,5,6,7,8,9,10}; int i 0; for(i 0; i 9; i) { printf(%d ,arr[i]); } return 0; }打印结果如下3.2数组的输入我们有了下标还可以根据自己的需要对数组输入想要的值如下#includestdio.h int main() { int arr[10] {1,2,3,4,5,6,7,8,9,10}; int i 0; for(i 0; i 9; i) { scanf(%d,arr[i]); } for(i 0; i 9; i) { printf(%d ,arr[i]); } return 0; }结果如下4.一维数组在内存中的存储有了前面的知识我们其实使用数组基本没有什么障碍了如果我们要深入数组我们最好能了解一下数组在内存中的存储。依次打印数组元素的地址这里我们要使用到一个占位符%p%p是专门用来打印指针、内存地址。#includestdio.h int main() { int arr[10] {1,2,3,4,5,6,7,8,9,10}; int i 0; for(i 0; i 9; i) { printf(arr[%d] %p\n,i,arr[i]);//记得要加上取地址 } return 0; }输出结果为从输出的结果中我们可以看出数组随着下标的增长地址是由小到大变化的然后相邻两个元素之间相差4因为一个整型是4个字节。所以数组在内存中是连续存放的。数组元素在内存中是连续存放的5.sizeof计算数组元素个数sizeof是C语言中的一个关键字是可以计算类型或者变量大小的其实sizeof也可以计算数组的大小。比如#includestdio.h int main() { int arr[10] {1,2,3,4,5,6,7,8,9,10}; printf(%d\n,sizeof(arr)); //结果是40 return 0; }输出的结果是40计算的是数组所占内存空间总大小单位是字节。因为数组中每个元素的类型是相同的那只要计算出一个元素所占字节的个数数组的元素个数就能算出来。一般选择第一个元素arr[0]算大小就可以。#includestdio.h int main() { int arr[10] {1,2,3,4,5,6,7,8,9,10}; printf(%d\n,sizeof(arr[0])); return 0; }我们知道了单个元素的大小我们就可以计算整个数组有多少个元素如下所示#includestdio.h int main() { int arr[10] {0};//全部初始化为零 printf(%d\n,sizeof(arr)/sizeof(arr[0])); return 0; }这里的输出结果为10也就是有十个元素以后在代码中需要数组元素个数的地方就不用固定写死了使用上面的计算不管数组怎么变化计算出的大小也就随着变化了比如该成int arr[20] {0};代码sz sizeofarr/ sizeofarr[0];不用改自动算出20。循环就可以写#includestdio.h int main() { int arr[10] {0}; int sz sizeof(arr)/sizeof(arr[0]); for(i 0; i sz; i) { printf(%d ,arr[i]); } return 0; }不用手动写死 i 10。6.二维数组的创建6.1二维数组的概念二维数组就是把一维数组当做数组的元素二维数组作为数组元素的数组被称为三维数组二维以上的数组统称为多維数组。整型、整型一维数组、整型二维数组6.2二维数组的创建type arr_name[常量值1][常量值2]例如int arr[2][5]; //表示有2行 每一行有5个元素double data[2][8]; //表示有2行每一行有8个元素7.二维数组的初始化在创建变量或者数组的时候给定一些初始值被称为初始化。然后二维数组的初始化跟一维数组的初始化一样也是使用大括号进行初始化的。7.1不完全初始化int arr1[3][5] {1,2,3}; int arr2[3][5] {0};7.2完全初始化int arr3[3][5] {1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7};7.3按照行初始化int arr4[3][5] {{1,2},{3,4},{5,6}};7.4初始化时省略行但是不能省略列int arr5[][5] {1,2,3}; int arr6[][5] {1,2,3,4,5,6,7}; int arr7[][5] {{1,2},{3,4},{5,6}};8.二维数组的使用8.1二维数组的下标因为二维数组是有行和列的只要锁定了行和列就能锁定数组中的一个元素。C语言规定二维数组行是从0开始的列也是从0开始的如下图所示最上面的列号最左边的是行号比如第2行第2列这个数就是5我们能通过下标快速定位一个元素。我们用代码试一下8.2二维数组的输入和输出对于二维数组我们也可以借助嵌套循环进行实现输入和输出代码操作如下#includestdio.h int main() { int arr[3][5] { 1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7 }; int i 0; //输入 for (i 0; i 3; i)//先产生行号 { int j 0; for (j 0; j 5; j)//再产生列号 { scanf(%d, arr[i][j]); } } //输出 for (i 0; i 3; i)//先产生行号 { int j 0; for (j 0; j 5; j)//再产生列号 { printf(%d , arr[i][j]); } printf(\n); } return 0; }输入和输出结果如下9.二维数组在内存中的存储像一维数组应用我们可以通过循环将二维数组中的所有元素的地址进行打印#includestdio.h int main() { int arr[3][5] { 1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7 }; int i 0; for (i 0; i 3; i)//先产生行号 { int j 0; for (j 0; j 5; j)//再产生列号 { printf(arr[%d][%d] %p\n, i, j, arr[i][j]); } } return 0; }输出的结果如下从输出的结果来看每一行内部的每个元素都是都是相邻的地址之间相差4个字节跨行位置处的两个元素如arr[0][4]和arr[1][0]之间也是差4个字节所以二维数组中的每个元素都是连续存放的。10.c99中的变长数组在c99标准之前C语言在创建数组的时候数组大小的指定只能使用常量、常量表达式或者如果我们初始化数据的话可以省略数组大小。如int arr1[10]; int arr2[35]; int arr3[] {1,2,3};这样的语法限制让我们创建数组就不够灵活有时候数组大了浪费空间有时候小了不够用的。c99中给一个变长数组variable-length array简称VLA的新特性允许我们可以使用变量指定数组大小。如下代码int n a b; int arr[n];上面示例中数组arr就是变长数组因为它的长度取决于变量n的值编译器没法事先确定只有运行时才能知道n是多少。因此变长数组不能初始化。但是VS2026上虽然支持大部分c99的语法没有支持c99的变长数组。如果输入则会出现如下情况VS不支持因为VS默认使用msvc这个编译器msvc这个编译器不支持c99中的变长数组但是可以在VS中下载clang这个编译器组件。第一步在找到你下载VS时的Visual Studio installer。第二步打开后点击修改第三步找到并勾选然后修改就等。第四步在Visual Studio installer那里点启动然后打开项目之后右击鼠标点属性。第五步在“平台工具集”右边下拉列表中选择LLVMclang-cl然后应用就可以了。然后你就可以尝试一下代码#include stdio.h int main() { int n 0; scanf(%d, n); int arr[n]; int i 0; for (i 0; i n; i) { scanf(%d, arr[i]); } for (i 0; i n; i) { printf(%d, arr[i]); } return 0; }11.数组练习练习1多个字符从两端移动向中间汇聚#includestdio.h #includestring.h int main() { char arr1[] welcome to bit...; char arr2[] #################; int left 0; int right strlen(arr1) - 1;//strlen计算有效字符个数 printf(%s\n, arr2);//先打印出还未操作的 while(left right)//arr1代替arr2的当左边加右边减当左边小于等于右边就停止 { arr2[left] arr1[left]; arr2[right] arr1[right]; left; right--; printf(%s\n, arr2);//这个操作完了的 } return 0; }练习2二分查找题目给定一个升序的整型数组在这个数组中查找到指定的值n找到了就打印“找不到”。对于这个我们首先是想到的循环遍历如下所示#includestdio.h int main() { int arr[10] { 1,2,3,4,5,6,7,8,9,10 }; int k 7; int sz sizeof(arr) / sizeof(arr[0]); int i 0; for (i 0; i sz; i) { if (arr[i] k) { printf(找到了\n); break; } } if (i sz) { printf(没找到\n); } return 0; }循环虽然能实现但是效率太慢了。比如我买了一双鞋闹气问我多少钱我说不超过300元。你还是好奇你想知道到底多少我就让你猜你会1,2,3,4...这样吗显然很慢一般你都会猜中间数字比如150然后看大了还是小了这就是二分查找也叫折半查找。代码实现如下#includestdio.h int main() { int arr[10] { 1,2,3,4,5,6,7,8,9,10 }; int k 7; int sz sizeof(arr) / sizeof(arr[0]); int left 0; int right sz - 1; while (left right) { int mid (left right) / 2; if (arr[mid] k) { left mid 1; } else if (arr[mid] k) { right mid - 1; } else { printf(找到了,下标是%d\n,mid); break; } } if (left right) { printf(没找到\n); } return 0; }求中间元素的下标使用midleft right/ 2如果left和right比较大的时候可能存在问题例如可以使用下面的这种方式left (right - left) / 2#includestdio.h int main() { //INT_MAX整型能表示的最大值 int left 2147483646;//减了1 int right 2147483646; printf(%d\n, left (right - left) / 2); return 0; }小结数组是 C 语言中非常重要的基础知识后面学习字符串、指针、函数、结构体以及数据结构时都会频繁用到数组。刚开始学习数组的时候可能会觉得下标、内存地址、sizeof、二维数组这些内容有点多但其实把它们联系起来理解就会简单很多数组是一组相同类型数据的集合 → 数据在内存中连续存储 → 通过下标访问元素 → 通过循环批量操作数据。学习 C 语言不能只停留在“看懂代码”一定要自己敲一遍、运行一遍再尝试修改代码。如果文章中有错误或者表述不准确的地方还请大家多多包涵也欢迎大家在评论区指出。有什么不懂的地方也可以一起交流学习。我会继续记录自己学习 C 语言的过程把学习过程中遇到的知识点、代码、踩过的坑以及一些自己的理解整理成博客希望能够和大家一起进步。本文相关代码已经整理到 Giteehttps://gitee.com/ZhiWeiCoder/student_c如果这篇文章对你有一点帮助欢迎点赞、收藏、评论、关注也可以给我的代码仓库点个关注 ❤️C语言学习还在继续下一篇继续学习编程没有捷径先把每一个知识点真正搞懂再慢慢把它们串起来。一起学习一起进步。

相关新闻

最新新闻

RAG技术面试核心考察点与应对策略

RAG技术面试核心考察点与应对策略

1. RAG技术面试的核心考察点最近在技术社区看到不少同行讨论RAG(检索增强生成)相关的面试经历,发现很多候选人在这个环节表现不佳。作为经历过多次RAG项目实战的老兵,我想分享几个面试官最爱深挖的问题方向。RAG面试的核心考察点通…

2026/8/23 19:56:50
C++可变模板参数:从原理到实战的类型安全编程利器

C++可变模板参数:从原理到实战的类型安全编程利器

1. 从“固定”到“无限”:为什么我们需要可变模板参数? 在C的世界里,函数和类模板的威力在于它们能让我们编写与类型无关的通用代码。但很长一段时间里,这种“通用性”有一个明显的天花板:参数的数量是固定的。你写一个…

2026/8/23 19:56:50
基于Dify工作流构建Markdown转Word自动化服务

基于Dify工作流构建Markdown转Word自动化服务

你有没有遇到过这样的场景:花了半天时间,用 Markdown 精心整理了一份技术文档、项目报告或者 API 说明,格式清晰,结构分明。但当你需要把它交给产品经理、客户或者不熟悉 Markdown 的同事时,对方却要求:“能…

2026/8/23 19:56:50
C++与PPO强化学习实战:从零构建AI角斗士对抗僵尸仿真环境

C++与PPO强化学习实战:从零构建AI角斗士对抗僵尸仿真环境

这次我们来看一个名为“AI角斗士学习对抗僵尸”的项目,它不是一个现成的游戏,而是一个使用C和SFML图形库,结合强化学习(特别是PPO算法)来训练智能体(角斗士)对抗僵尸的仿真环境。项目由Pezzza开…

2026/8/23 19:56:50
嵌入式系统数据存储管理:从介质选型到高可靠架构设计实战

嵌入式系统数据存储管理:从介质选型到高可靠架构设计实战

1. 项目概述:为什么嵌入式系统的数据存储是个“老大难”?干了十几年嵌入式开发,从8位单片机到现在的多核ARM Cortex-A系列,项目做了不下百个。我发现一个挺有意思的现象:很多工程师在项目初期,会把绝大部分…

2026/8/23 19:56:50
整数规划求解利器:分枝定界法核心原理与工程实践详解

整数规划求解利器:分枝定界法核心原理与工程实践详解

1. 项目概述:从“算不完”到“算得巧”的整数规划求解之路 搞数学建模或者运筹优化的朋友,对“整数规划”这四个字一定不陌生。它就像是现实世界决策问题的“标准照”——很多决策变量天然就是整数,比如你要建几个工厂(0或1&#…

2026/8/23 19:51:49