C语言【基础篇】之数组——解锁多维与动态数组的编程奥秘
数组
- 🚀前言
- 🦜数组的由来与用途
- 🌟一维数组详解
- 🖊️二维数组进阶
- 💯动态数组原理
- 🤔常见误区扫盲
- 💻学习路径建议
- ✍️总结
🚀前言
大家好!我是 EnigmaCoder。本文收录于我的专栏 C,感谢您的支持!
- 前文我们介绍了C语言中的流程控制。
- 链接: C语言【基础篇】之流程控制——掌握三大结构的奥秘
- 本文我们将介绍C语言中的重要篇章——数组。

🦜数组的由来与用途
- 1.1 为什么要用数组?
想象一个现实案例:学校图书馆需要管理5000本图书的借阅状态。如果使用单变量存储:
int book1_status, book2_status, ..., book5000_status;
- 这种方式存在三个
致命缺陷:-
- 变量命名工作量巨大
-
- 无法通过循环批量处理
-
- 内存分配零散难维护
-
数组的出现完美解决这些问题:
int book_status[5000]; // 一条语句声明全部状态变量
1.2 内存组织形式
数组的每个元素在内存中按顺序紧密排列,假设声明int arr[5]:
内存地址 | 元素值
0x1000 | arr[0]
0x1004 | arr[1]
0x1008 | arr[2]
0x100C | arr[3]
0x1010 | arr[4]
这种连续存储特性带来两个优势:
- 快速定位:通过
首地址+偏移直接访问任何元素 - 批量处理:适合循环结构统一操作
🌟一维数组详解
- 2.1 定义语法
元素类型 数组名[元素个数];
-
元素类型:确定每个存储单元占用的内存大小(如
int占4字节) -
元素个数:必须是常量表达式(C99后支持变量长度数组)
-
示例:
/* 完全初始化 */ int primes[5] = {2,3,5,7,11};/* 自动补齐初始化 */ double measures[3] = {1.5}; // 剩余元素自动补0.0 /* 省略长度声明 */ char colors[] = {'R','G','B'}; // 编译器自动计算为3元素 -
2.2 安全访问机制
核心隐患:数组越界
下图展示一个典型越界错误的内存覆盖场景:
[合法区域] | arr[0] | arr[1] | arr[2] | ...
地址 0x1000 0x1004 0x1008
索引越界访问arr[3] → 侵入0x100C未知区域
防范措施:
// 使用安全范围检测
#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))for(int i=0; i<ARRAY_SIZE(arr); i++){// 安全操作
}
🖊️二维数组进阶
-
3.1 多维的本质
二维数组两种的理解视角:-
- 矩阵视角:表格式数据排列,适合表达行列表格数据
int matrix[3][4]; // 3行4列矩阵-
- 数组的数组:本质是嵌套的一维数组,每个元素为一维数组
// 等价写法 typedef int Row[4]; Row matrix[3]; -
-
3.2 初始化差异分析
完全初始化与分行初始化的区别:
// 紧凑方式初始化
int a[2][3] = {1,2,3,4,5,6};// 分行初始化(推荐)
int b[2][3] = {{1,2,3},{4,5,6}
};// 验证排列顺序
printf("%d", a[1][2]); // 输出6
printf("%d", b[1][2]); // 同样输出6
💯动态数组原理
- 4.1 内存生命周期管理
对比三种数组存储期特性:
| 数组类型 | 存储位置 | 声明周期 | 使用场景 |
|---|---|---|---|
| 全局数组 | 数据段 | 程序运行全程 | 配置参数 |
| 局部静态数组 | 数据段 | 函数调用保持 | 持久缓存 |
| 局部自动数组 | 栈空间 | 函数退出释放 | 临时缓冲区 |
| 动态分配数组 | 堆空间 | 手动控制释放 | 大数据存储 |
- 4.2 动态扩容标准范式
六步骤保证内存安全:
int *arr = NULL; // Step1: 初始化指针为NULL
int size = 0;// 初始分配
arr = malloc(5*sizeof(int)); // Step2: 首次分配
size = 5;// 扩容操作
int *temp = realloc(arr, 10*sizeof(int)); // Step3: 使用中间变量
if(temp == NULL) { // Step4: 检测分配结果 free(arr); // Step5: 原保留内存 exit();
1}=arr temp; // Step6: 安全替换指针
size = 10;
🤔常见误区扫盲
Q1:数组名是常指针吗?
- 正确理解:数组名在多数场景可视为指向首元素的指针常量,但
sizeof(arr)会返回数组总长度而非指针大小,这体现了类型系统的抽象层级。
Q2:数组作为参数传递的本质?
// 函数声明等效写法
void func(int arr[]);
void func(int *arr);
数组参数实际传递的是指针,因此修改形参会影响实参数组内容。
Q3:为何下标可以是变量?
编译原理层面,数组访问会被转换为指针运算:
arr[i] 等价于 *(arr + i)
只要i在合法范围内,允许运行时动态计算索引。
💻学习路径建议
理论到实践步骤:
- 手工绘制内存图:理解数组物理存储形态
- 调试观察地址变化:验证元素地址计算规则
- 手写模拟数组操作:不使用[]实现数组访问
进阶学习方向:
- 数组与指针的交集与差异
- 数组在处理字符串中的特殊应用
- 动态数组与链表结构的优劣比较
✍️总结
本文主要讲解C语言中数组的相关知识,包括一维数组二维数组以及动态数组。如果对您有帮助,不妨点个赞👍👍👍
相关文章:
C语言【基础篇】之数组——解锁多维与动态数组的编程奥秘
数组 🚀前言🦜数组的由来与用途🌟一维数组详解🖊️二维数组进阶💯动态数组原理🤔常见误区扫盲💻学习路径建议✍️总结 🚀前言 大家好!我是 EnigmaCoder。本文收录于我的专…...
C++ 字符串编码转换
UTF8 的string 转 UTF16 的 wstring std::wstring Utf8ToUtf16(const std::string& utf8Str) { // 获取 UTF-16 字符串所需的缓冲区大小 int wstrLength = MultiByteToWideChar(CP_UTF8, 0, utf8Str.c_str(), -1, NULL, 0); if (wstrLength == 0) { // …...
通讯录管理小程序
通讯录管理系统 是对c基础语法的巩固,比较简单的一个小程序,重点在于养成良好的c代码习惯。 通讯录是一个可以记录亲人、好友信息的工具。 本教程主要利用C来实现一个通讯录管理系统 下面是一些需要实现的功能: 1. 添加联系人 功能描述&…...
掌握API和控制点(从Java到JNI接口)_38 JNI从C调用Java函数 01
1. Why? 将控制点下移到下C/C层 对古典视角的反思 App接近User,所以App在整体架构里,是主导者,拥有控制权。所以, App是架构的控制点所在。Java函数调用C/C层函数,是合理的。 但是EIT造形告诉我们: App…...
理解UML中的四种关系:依赖、关联、泛化和实现
在软件工程中,统一建模语言(UML)是一种广泛使用的工具,用于可视化、设计、构造和文档化软件系统。UML提供了多种图表类型,如类图、用例图、序列图等,帮助开发者和设计师更好地理解系统的结构和行为。在UML中…...
windows蓝牙驱动开发-蓝牙 LE 邻近感应配置文件
邻近感应检测是蓝牙低功耗 (LE) 的常见用途。 本部分提供了创建可用于开发 UWP 设备应用的邻近感应配置文件的设备实现的指南。 在开发此应用之前,应熟悉蓝牙 LE 函数和蓝牙 LE 邻近感应配置文件规范。 示例服务声明 蓝牙低功耗引入了一个新的物理层,…...
【截图】selenium自动通过浏览器截取指定元素div的图片
【截图】selenium自动通过浏览器截取指定元素div的图片 思路 截取完整网页截图 通过元素的坐标 截图到指定位置的图片 前提是已经获取到 driver 了 # 定位目标divtarget_div driver.find_element(By.CLASS_NAME, headlines-right)# 获取div的位置和大小location target_div…...
【算法】动态规划专题⑨ —— 二维费用背包问题 python
目录 前置知识进入正题实战演练 前置知识 【算法】动态规划专题⑤ —— 0-1背包问题 滚动数组优化 python 进入正题 二维费用背包问题 方法思路 二维费用背包问题在传统背包问题的基础上增加了第二个维度的限制(如重量)。 每个物品具有两种费用&#x…...
免费windows pdf编辑工具Epdf
Epdf(完全免费) 作者:不染心 时间:2025/2/6 Github: https://github.com/dog-tired/Epdf Epdf Epdf 是一款使用 Rust 编写的 PDF 编辑器,目前仍在开发中。它提供了一系列实用的命令行选项,方便用户对 PDF …...
MVCC机制深度解析
在数据库管理系统中,多版本并发控制(MVCC,Multi-Version Concurrency Control)是一种用于提高数据库并发性能的技术。它通过在同一数据项上存储多个版本,允许事务在读取数据时不必等待其他事务的完成,从而提…...
C++:类和对象初识
C:类和对象初识 前言类的引入与定义引入定义类的两种定义方法1. 声明和定义全部放在类体中2. 声明和定义分离式 类的成员变量命名规则 类的访问限定符及封装访问限定符封装 类的作用域与实例化类的作用域类实例化实例化方式: 类对象模型类对象的大小存储…...
伪分布式Spark3.4.4安装
参考:Spark2.1.0入门:Spark的安装和使用_厦大数据库实验室博客 我的版本: hadoop 3.1.3 hbase 2.2.2 java openjdk version "1.8.0_432" 问了chatgpt,建议下载Spark3.4.4,不适合下载Spark 2.1.0: step1 Spark下载…...
kafka服务端之控制器
文章目录 概述控制器的选举与故障恢复控制器的选举故障恢复 优雅关闭分区leader的选举 概述 在Kafka集群中会有一个或多个broker,其中有一个broker会被选举为控制器(Kafka Controler),它负责管理整个集群中所有分区和副本的状态。…...
element-plus el-tree-select 修改 value 字段
element-plus el-tree-select 修改 value 字段 ,不显示label 需要注意两个地方: <el-tree-select v-model"value" :data"data" multiple :render-after-expand"false" show-checkbox style"width: 240px" …...
SQL最佳实践(笔记)
写在前面: 之前baeldung的Java Weekly Reviews里面推荐了一篇关于SQL优化的文章,正好最近在学习数据库相关知识,记一些学习笔记 原文地址:SQL Best Practices Every Java Engineer Must Know 1. 使用索引 使用索引…...
在 Java 中执行一个复杂的 SQL 查询(包含多表连接、子查询和聚合函数),如何确保查询的性能?请列举至少三条措施。请简要描述其工作原理?
在Java中执行复杂的SQL查询时,确保查询性能是非常重要的。 以下是三条关键措施,以及它们的详细解释、代码示例和实际开发中的注意事项。 1. 使用索引 索引是提高数据库查询性能的最基本手段之一。通过在查询条件中使用的列上创建索引,可以…...
java将list转成树结构
首先是实体类 public class DwdCusPtlSelectDto {//idprivate String key;//值private String value;//中文名private String title;private List<DwdCusPtlSelectDto> children;private String parentId;public void addChild(DwdCusPtlSelectDto child) {if(this.chil…...
【R语言】数据分析
一、描述性统计量 借助R语言内置的airquality数据集进行简单地演示: 1、集中趋势:均值和中位数 head(airquality) # 求集中趋势 mean(airquality$Ozone, na.rmT) # 求均值 median(airquality$Ozone, na.rmT) # 求中位数 2、众数 众数(mod…...
传输层协议 UDP 与 TCP
🌈 个人主页:Zfox_ 🔥 系列专栏:Linux 目录 一:🔥 前置复盘🦋 传输层🦋 再谈端口号🦋 端口号范围划分🦋 认识知名端口号 (Well-Know Port Number) 二…...
Linux 调用可执行程序
Linux 调用可执行程序 1. system() 函数1.1 system() 函数的声明1.2 system() 函数的不同场景返回值1.3 system() 函数的代码示例 2. exec() 函数族2.1 exec() 函数族的声明2.2 exec() 函数族执行失败的情况2.3 exec() 函数族的代码示例 3. exec() 与 system() 的区别以及使用注…...
Java/Kotlin双语革命性ORM框架Jimmer(一)——介绍与简单使用
概览 Jimmer是一个Java/Kotlin双语框架 包含一个革命性的ORM 以此ORM为基础打造了一套综合性方案解决方案,包括 DTO语言 更全面更强大的缓存机制,以及高度自动化的缓存一致性 更强大客户端文档和代码生成能力,包括Jimmer独创的远程异常 …...
剪辑学习整理
文章目录 1. 剪辑介绍 1. 剪辑介绍 剪辑可以干什么?剪辑分为哪些种类? https://www.bilibili.com/video/BV15r421p7aF/?spm_id_from333.337.search-card.all.click&vd_source5534adbd427e3b01c725714cd93961af 学完剪辑之后如何找工作or兼职&#…...
IDEA查看项目依赖包及其版本
一.IDEA将现有项目转换为Maven项目 在IntelliJ IDEA中,将现有项目转换为Maven项目是一个常见的需求,可以通过几种不同的方法来实现。Maven是一个强大的构建工具,它可以帮助自动化项目的构建过程,管理依赖关系,以及其他许多方面。 添加Maven支持 如果你的项目还没有pom.xm…...
centos虚拟机迁移没有ip的问题
故事背景,我们的centos虚拟机本来是好好的,但是拷贝到其他电脑上就不能分配ip,我个人觉得这个vmware他们软件应该搞定这个啊,因为这个问题是每次都会出现的。 网络选桥接 网络启动失败 service network restart Restarting netw…...
Java 大视界 -- Java 大数据在智能供应链中的应用与优化(76)
💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也…...
Java中的继承及相关概念
在 Java 中,继承是一种允许一个类继承另一个类的特性。通过继承,子类可以获取父类的属性和方法,这有助于减少代码冗余并提高代码的可维护性。以下是关于文件内容的相关分析和知识点总结: 一、继承的核心概念 1.继承的语法 Java …...
赛博算命之 ”梅花易数“ 的 “JAVA“ 实现 ——从玄学到科学的探索
hello~朋友们!好久不见! 今天给大家带来赛博算命第三期——梅花易数的java实现 赛博算命系列文章: 周易六十四卦 掐指一算——小六壬 更多优质文章:个人主页 JAVA系列:JAVA 大佬们互三哦~互三必回!…...
DNS攻击方式有哪些,应该采取哪些应对措施?
在当今数字化时代,网络已成为人们生活和工作不可或缺的一部分。而 DNS(域名系统)作为互联网的关键基础设施,如同电话簿一般,将人们易于记忆的域名转换为计算机能够识别的 IP 地址,让我们能够轻松访问各类网…...
即梦(Dreamina)技术浅析(六):多模态生成模型
多模态生成模型是即梦(Dreamina)的核心技术之一,旨在结合文本和图像信息,生成更符合用户需求的视觉内容。多模态生成模型通过整合不同类型的数据(如文本和图像),能够实现更丰富、更精准的生成效果。 1. 基本原理 1.1 多模态生成模型概述 多模态生成模型的目标是结合不…...
如何优化爬虫以提高搜索效率
在数据采集和网络爬虫领域,优化爬虫性能是提升数据采集效率的关键。随着网页结构的日益复杂和数据量的不断增长,高效的爬虫能够显著降低运行时间和资源成本。本文将详细介绍如何优化爬虫以提高搜索效率,包括选择合适的工具、优化代码逻辑、使…...
