【C语言】第五课 结构体与内存对齐​​

C语言基础——专栏索引篇 前言 C语言是编程初学者最需要掌握的一个语言,对C语言了解地足够透彻,对于对其他语言的理解就会更加轻松。而且正是由于其没有那么大的便捷性,对我们编程的能力会有更多的提升。 这篇集合是我对C语言基础语法的一个讲解集合,我会尽可能写的详细和透彻深入,帮助大家更轻松地掌握C语言。 我会努力提高更新文章的速度,使得这个体系变得更加完善。 目录 第一课:一个有趣的运算符-------------------... 阅读详情

🧱 1. 结构体的定义与访问

结构体(struct)允许你将多个不同类型的变量组合成一个单一的复合类型,这在表示现实世界的实体(如学生、商品等)时非常有用。

  • 定义结构体:使用 struct 关键字来定义一个新的结构体类型。

    /* 定义一个名为Student的结构体类型 */
    struct Student {
        char name[20];  // 姓名
        int age;        // 年龄
        double height;  // 身高
    };
    

    定义结构体时,可以同时声明变量,也可以先定义类型再声明变量:

    /* 方式1: 定义类型的同时声明变量 */
    struct Point {
        int x;
        int y;
    } p1, p2; // 变量p1和p2
    
    /* 方式2: 先定义类型,再声明变量 */
    struct Point p3; // 另一个Point变量
    

    还可以使用 typedef 简化类型名:

    typedef struct Employee {
        int id;
        char dept[10];
    } Emp; // 现在可以用`Emp`代替`struct Employee`
    
    Emp e1; // 变量声明
    
  • 初始化结构体:可以在声明时使用大括号 {} 初始化。

    struct Student stu1 = {"Alice", 20, 1.65};
    
  • 访问结构体成员:使用点号 . 操作符访问结构体变量的成员。如果通过指针访问,则使用箭头 -> 操作符。

    struct Student s;
    s.age = 21; // 直接访问赋值
    
    struct Student *ptr = &s;
    ptr->age = 22; // 通过指针访问赋值
    printf("Age: %d\n", ptr->age);
    

🧠 2. 内存对齐原则

CPU并非逐字节访问内存,而是以特定字节数(如2、4、8字节)为块(称为内存访问粒度)进行读取。如果数据未在自然对齐的边界上,CPU可能需要进行多次内存访问并拼接数据,这会降低效率,在某些架构(如ARM)上甚至可能导致硬件异常。

内存对齐规则主要有三条:

  1. 起始地址对齐:结构体的第一个成员从偏移量(offset)为0的地址处开始存放。
  2. 成员地址对齐:结构体的每个成员变量,其起始地址必须是 min(编译器默认对齐数, 该成员类型大小) 的整数倍。Visual Studio默认对齐数为8,Linux/GCC下则没有默认对齐数,以其类型大小为准。
    • 例如,在VS中,int(4字节)的对齐数是 min(8, 4) = 4,故其地址必须是4的倍数。
  3. 结构体整体大小对齐:整个结构体的总大小必须是 所有成员中“最大对齐数” (每个成员的对齐数中的最大值)的整数倍。如果不是,编译器会在末尾添加填充字节(Padding)以满足此条件。

为什么需要内存对齐?
主要是为了性能和可移植性。对齐的数据访问速度更快,且某些硬件平台根本不支持非对齐访问。

📐 3. 计算结构体大小

理解规则后,我们可以手动计算结构体大小。

  • 示例1:简单结构体

    struct S1 {
        char a;     // 大小1字节,对齐数1 (min(8,1))
        int b;      // 大小4字节,对齐数4 (min(8,4))
        short c;    // 大小2字节,对齐数2 (min(8,2))
    };
    

    假设起始地址为0:

    • a 放在偏移量0。
    • b 需放在4的倍数处,故偏移量1-3填充,b 从偏移量4开始存放(4-7)。
    • c 对齐数为2,可从偏移量8开始存放(8-9)。
    • 当前总大小:0-9 = 10字节。
    • 结构体最大对齐数是 max(1,4,2)=4,10不是4的倍数,需在末尾填充2字节(偏移量10-11)。
    • 最终 sizeof(S1) = 12 字节。
  • 示例2:调整成员顺序优化

    struct S2 {
        int b;      // 4字节,对齐数4,偏移量0-3
        short c;    // 2字节,对齐数2,偏移量4-5
        char a;     // 1字节,对齐数1,偏移量6
        // 填充1字节使总大小为最大对齐数(4)的倍数 (7->8)
    };
    

    最终 sizeof(S2) = 8 字节。
    优化技巧:将占用空间大的成员(和对齐数大的成员)放在前面,通常可减少填充字节,节省内存。

  • 示例3:嵌套结构体

    struct Inner {
        double d;   // 8字节,对齐数8
        char e;     // 1字节,对齐数1
        // 编译器可能在e后填充若干字节,使Inner自身大小是8的倍数 (例如16或24,取决于规则)
    };
    
    struct Outer {
        int a;          // 4字节,对齐数4
        struct Inner s;  // Inner的对齐数取其自身最大对齐数(8)
        // 因此s的起始地址必须是8的倍数
        short b;        // 2字节,对齐数2
    };
    

    计算嵌套结构体大小时,规则类似,但需注意内部结构体的自身对齐要求。

  • 使用 #pragma pack 修改默认对齐数
    可以使用 #pragma pack(n) 指令指定新的默认对齐数(n通常是1, 2, 4, 8…)。

    #pragma pack(push, 1) // 将当前对齐设置压栈,并设置对齐数为1
    struct PackedStruct {
        char a;
        int b;
        short c;
    }; // 理论上 sizeof(PackedStruct) == 1+4+2 = 7
    #pragma pack(pop)      // 恢复之前的对齐设置
    

    注意:慎用 #pragma pack。虽然节省内存,但可能导致性能下降,且在某些硬件平台上访问未对齐数据会引发崩溃。常用于网络协议包、硬件寄存器映射等需要精确控制内存布局的场景。

🔍 4. 观察内存布局(逆向重点)

在逆向工程中,分析二进制文件常需推断数据结构布局。调试器是观察内存布局的利器。

  • 使用 offsetof 宏:
    offsetof 宏(定义于 stddef.h)可获取结构体成员在其中的偏移量。

    #include <stddef.h>
    printf("Offset of 'b' in S1: %zu\n", offsetof(struct S1, b)); // 输出4
    
  • 在Visual Studio中观察:

    1. 在调试模式(按 F5)下运行程序。
    2. 在代码中设置断点。
    3. 当程序在断点处停止时,可以通过监视窗口(Watch Window)查看结构体变量,并展开观察其成员的值和地址。
    4. 更强大的是内存窗口(Memory Window)(调试 > 窗口 > 内存),你可以输入结构体变量的地址(如 &s1),直接查看其内存字节,非常有助于分析填充字节和实际布局。
LVGL v8.3 图片显示与解码缓存实战:PNG 上屏、C 数组与文件双方案 LVGL v8.3 图片两种存储方式、PNG/JPG 上屏解码器挂载、LV_IMG_CACHE_DEF_SIZE 缓存调优、手动预解码头像有效性判断,及"缓存被动画清空"真实踩坑。 阅读详情

相关推荐

基于MATLAB的太阳能光伏电力仿真,模拟每日太阳能发电,可视化功率曲线,并通过数值积分计算总能量输出。.zip

1.版本:matlab2014a/2019b/2024b 2.附赠案例数据可直接运行。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

C语言入门——第五课

一、Q&A 1.#include两种引用方式 2.bool类型与C语言 3.函数的类型 4.指针的声明 5.函数的调用和取地址 6.exit函数 7.可变参 二、结构体:输入输出、结构体指针、指针调用、结构体字符对齐 三、文件:文件的分类、读写、打开、关闭 四、关键字sizeof和volatile

m0_54231818的博客 375

人脸识别签到考勤系统实战源码

这是一套可直接运行的人脸识别智能签到考勤系统,基于OpenCV YuNet人脸检测与SFace特征识别实现,全程本机运行,数据保存在本地SQLite,不上传任何服务器。配套交付完整Python源码、9章实战教程(md/html/pdf三种格式)、逐步骤操作截图和答辩PPT讲解。 系统围绕五个功能模块展开:人脸注册支持照片批量导入并提取特征入库;识别签到支持照片或摄像头两种方式,实时框出人脸并标注姓名、相似度与考勤状态;考勤规则引擎按config.py里配置的上下班时间与宽限分钟,自动判定迟到、早退、缺勤;Tkinter管理面板完成人员管理、流水查询与月度汇总;最后通过openpyxl一键导出整月考勤矩阵,正常绿、迟到黄、缺勤红,Excel打开即用。 选型上特意选了YuNet+SFace路线:纯pip安装免编译,CPU单帧识别不到100ms,两个ONNX模型共约37MB,出自OpenCV官方模型仓库,毕设报告引用有据可查。教程第7章整理了16条Windows下真实踩过的报错及排查方法,第8章给出换模型、换人脸、加功能的二次开发路径。 适合做计算机视觉方向毕设或课程设计的学生,也适合想给班级、实验室、小团队搭一套本地签到工具的Python学习者。运行环境为Python 3.9以上、Windows 10/11,不需要GPU。 使用时先pip install -r requirements.txt装齐依赖,再运行download_data.py下载模型,最后启动main.py即可进入图形界面;命令行register、recognize、report子命令也可脱离界面单独调用。

C++学习第六课:内存对齐、对象、this指针与构造函数

本篇文章主要讲解了构造函数的相关内容,并简单复习了内存对齐的知识!

m0_74983085的博客 2039

【无人机航测】MATLAB重叠率与地面分辨率协同设计:航线间距及飞行方向优化系统 MATLAB 无人机航测重叠率设计|地面分辨率与航线间距计算

内容概要:本文档介绍了基于MATLAB R2025b开发的无人机航测重叠率与航线间距计算系统,旨在通过建立统一的航测几何计算体系,实现重叠率、地面分辨率与航线间距的动态协同设计。系统结合相机参数、飞行参数、地形数据与风场信息,通过自动化候选航向搜索与多目标优化,选择兼顾覆盖质量、飞行效率与安全性的最优航线方向。项目涵盖从参数输入、摄影测量计算、地形与安全修正,到候选路线生成、综合评价与结果可视化的全流程,并构建了五万组模拟数据用于算法验证与模型训练,支持桌面交互、批量处理与服务化部署,适用于多种复杂场景下的无人机航测任务规划。 适合人群:具备一定MATLAB编程基础和摄影测量知识的科研人员、工程技术人员及高校师生,尤其适合从事无人机航测、地理信息系统(GIS)、遥感与测绘等相关领域的从业者。 使用场景及目标:① 实现无人机航测任务中地面分辨率与航线间距的精确计算与动态优化;② 解决复杂地形与风场环境下航线方向选择困难、覆盖质量难以保障的问题;③ 通过自动化设计减少人为经验依赖,提升航测任务的可靠性与效率;④ 为后续的三维建模、正射影像生成与灾害应急评估等应用提供高质量的数据基础。 阅读建议:建议读者结合文中提供的完整代码示例与GUI界面设计,逐步实践参数配置、模型计算与结果分析流程。重点关注摄影测量公式推导、地形修正策略与多目标优化算法的实现细节,并利用模拟数据进行敏感性分析与模型验证,以深入理解系统的设计理念与工程应用价值。

【电力负荷预测】项目介绍 MATLAB实现基于BO-Transformer-LSTM贝叶斯优化算法(BO)优化Transformer-LSTM组合模型进行居民用户多步电力负荷预测(含模型描述及部分示例

内容概要:本文介绍了一个基于BO-Transformer-LSTM的组合模型,用于实现居民用户多步电力负荷预测的完整项目实例。该模型融合Transformer的全局注意力机制与LSTM的局部时序记忆能力,构建能够捕捉长时依赖与周期性特征的深度学习架构,并引入贝叶斯优化(BO)自动搜索最优超参数组合,提升预测精度与训练效率。项目涵盖从原始数据清洗、特征工程、滑动窗口样本构建、模型设计到超参数优化、反归一化及多步误差评估的全流程,强调时间顺序划分以防止信息泄露,并通过周期编码、外生变量融合等方式增强数据表达能力。文中提供了详细的MATLAB代码示例,包括数据预处理、网络搭建、贝叶斯优化配置和预测结果评估等关键步骤。 适合人群:具备一定机器学习和时间序列分析基础,熟悉MATLAB编程环境,从事电力系统预测、智能电网、负荷管理等相关领域的研究人员、工程师及研究生。 使用场景及目标:①应用于居民级或多用户聚合负荷的短期至中期多步预测(如未来24小时);②服务于配电系统运行调度、需求响应基线设定、家庭能源管理系统优化、分布式能源协调控制等实际工程场景;③为科研提供可复现的深度学习+贝叶斯优化的技术路线参考。 阅读建议:此资源以实际项目为导向,建议读者结合提供的代码逐步实现并调试模型,重点关注数据质量控制、时间特征编码、组合网络结构设计与贝叶斯优化稳定性之间的协同关系,在实践中深入理解多步预测中的误差累积机制与超参数敏感性问题。

C语言入门——第15节课

1.strcmp函数优化 2.结构体对齐 3.memset函数使用和编写 4.memcpy函数使用和编写 5.函数——编译链接过程和内存布局 6.函数的可见性 7.函数生存期——存储类型说明符 8.寄存器 9.汇编语言知识——基本指令 10.汇编语言——寻址方案

m0_54231818的博客 241

国央企创新负责人如何通过平台实现科研成果的快速识别与转化?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

如何比较两个结构体数组里的数字完全相同 c语言_C语言探索之旅 | 第二部分第六课:创建你自己的变量类型...

作者 谢恩铭,公众号「程序员联盟」(微信号:coderhub)。转载请注明出处。原文:https://www.jianshu.com/p/39b41aa5cca7内容简介前言定义一个 struct结构体的使用结构体指针unionenum总结第二部分第七课预告1. 前言上一课是 C语言探索之旅 | 第二部分第五课:预处理 ,应该是比较轻松的。这一课将会非常令人激动也很有意思,不过有些难度。众所周知,...

weixin_39564605的博客 703

PotPlayer自用皮肤

自用 PotPlayer 皮肤,仅微调了字体大小与颜色,是按个人习惯调整,未做适配性调整。

2-shell及常用命令-续.pdf

2-shell及常用命令-续.pdf

c语言 如何创建adt_C语言探索之旅 | 第二部分第六课:创建你自己的变量类型

内容简介前言定义一个 struct结构体的使用结构体指针unionenum总结第二部分第七课预告1. 前言上一课是 C语言探索之旅 | 第二部分第五课:预处理 ,应该是比较轻松的。这一课将会非常令人激动也很有意思,不过有些难度。众所周知,C语言是面向过程的编程语言,与 Java,C++,等面向对象的编程语言有所不同。在面向对象的编程语言中,有类(class)的概念。C语言是没有类这种“类...

weixin_39717704的博客 201

【顶级EI复现】基于KKT条件与分段解析优化的双有源桥DC-DC变换器软开关协同最小应力闭环控制方法(Simulink仿真实现)

内容概要:本文详细介绍了一种基于KKT(Karush-Kuhn-Tucker)最优性条件与分段解析优化技术的双有源桥(DAB)DC-DC变换器闭环控制方法,旨在实现软开关条件下器件电压和电流应力的协同最小化,从而提升变换器的转换效率与系统可靠性。该方法通过建立精确的数学模型,结合KKT条件进行优化求解,并采用分段解析策略提高实时控制性能,在Simulink环境中完成了完整的闭环控制系统建模与仿真验证。作为“顶级EI复现”级别的研究成果,内容涵盖控制算法设计、优化机制分析、仿真架构搭建及结果对比,具有较强的理论深度与工程应用价值,适用于电力电子高频化、高效化发展的前沿研究方向。; 适合人群:面向具备电力电子、自动控制或电气工程等相关专业背景,熟悉Simulink仿真平台,且从事科研工作1年以上的研究生、博士生及科研人员;特别适合致力于DC-DC变换器拓扑优化、软开关技术、最小化开关应力控制、能量高效传输等领域研究的专业人士。; 使用场景及目标:① 复现高水平EI期刊论文中的先进优化控制算法;② 掌握KKT条件在非线性约束优化问题中的具体应用;③ 深入理解DAB变换器在不同工况下的软开关实现机制与应力抑制策略;④ 构建高精度仿真模型以支撑学术论文撰写、科研项目申报或实际工程系统的控制方案设计。; 阅读建议:建议结合提供的Simulink仿真模型同步学习,重点关注KKT条件推导过程与分段解析优化模块的实现逻辑。由于内容涉及较强的数学建模与优化理论,推荐具备扎实的电路理论、现代控制理论及数值优化基础后再行研读,并可参考同系列“顶级EI复现”资源以构建系统性知识体系。

c语言个人通讯录管理系统实验报告_C语言探索之旅 | 第二部分第六课:创建你自己的变量类型...

内容简介前言定义一个 struct结构体的使用结构体指针unionenum总结第二部分第七课预告1. 前言上一课是 C语言探索之旅 | 第二部分第五课:预处理 ,应该是比较轻松的。这一课将会非常令人激动也很有意思,不过有些难度。众所周知,C语言是面向过程的编程语言,与 Java,C++,等面向对象的编程语言有所不同。在面向对象的编程语言中,有类(class)的概念。C语言是没有类这种“类...

weixin_36081148的博客 206

交错并联图腾柱PFC变换器仿真设计(Simulink仿真实现)

内容概要:本文档系统性地介绍了基于Simulink平台的“交错并联图腾柱PFC变换器”仿真设计,聚焦于高效率功率因数校正技术的建模与实现。内容涵盖双闭环控制策略(电压外环与电流内环)、PI控制器设计、交错并联结构优化以及图腾柱拓扑的工作原理,旨在提升系统动态响应性能、降低输入电流谐波含量并改善功率因数。文档不仅提供详细的仿真模型构建流程,还配套Mathcad计算书用于参数设计与功率等级扩展,并列举了多种相关电力电子变换器的仿真案例,如三相维也纳整流器、LLC谐振变换器、双向Buck-Boost电路等,形成了一套完整的电力电子系统仿真资源体系,适用于从理论分析到工程实践的全流程学习与研究。; 适合人群:电气工程、自动化、电力电子及相关专业的高校本科生、研究生,以及从事新能源发电、电源设计、电能质量治理、工业自动化等领域的研发工程师;具备基本电路理论知识和Simulink/Matlab使用经验者更佳。; 使用场景及目标:①支持高校课程设计、毕业设计或科研项目中对先进PFC拓扑的仿真验证与性能优化;②帮助工程技术人员快速掌握图腾柱PFC的核心控制逻辑与建模方法,缩短产品开发周期;③作为电力电子系统教学与技术培训的标准化参考案例,强化理论与实践结合能力。; 其他说明:文档由“荔枝科研社”整理发布,所有资源可通过指定公众号或百度网盘链接获取,建议按照目录顺序系统学习,并结合提供的Mathcad计算书、参考文献及仿真文件进行参数验证与二次开发,以深化理解与应用能力。

.NET+Vue企业级RBAC权限平台:开箱即用的生产就绪方案

RBAC(基于角色的访问控制)是企业系统安全治理的基础模型,其核心在于将用户、角色与权限解耦,通过动态能力组合实现细粒度管控。在真实工程中,RBAC需突破静态角色限制,支持时间维度授权、前后端双重鉴权、行级数据范围控制等关键能力。本文聚焦于一套已落地金融、政务、制造等多行业的生产级实现——基于.NET Minimal API与Vue 3的前后端分离架构,提供菜单/按钮/接口/数据四层权限控制,内置滑动过期JWT、Redis权限缓存、动态路由加载与权限指令等开箱即用能力,显著降低权限配置与审计成本。

weixin_33326218的博客 275

C语言探索之旅 | 第二部分第六课:创建你自己的变量类型

众所周知,C语言是面向过程的编程语言,与Java,C#等面向对象的编程语言有所不同。 在面向对象的编程语言中,有类的概念。C语言是没有类这种“类型”的,但是C语言就不能模拟“面向对象”编程了吗? 不,只要你设计得好,C语言也可以模拟面向对象编程。这一课我们学到的关于struct(结构体)的知识就可以使你有能力用C语言实现面向对象。 前面我们学习了指针,数组,字符串和预处理,掌握这些知识你的C语言水平已经还不错啦,但是我们岂能就此止步。C语言还可以让我们做一些更厉害的事情:创建你自己的变量类型。 我们可以将其

程序员联盟 1745

【Lua面试】2021年Lua面试题分享(4.25更新)

lua深拷贝和浅拷贝的区别?如何实现深拷贝? lua中ipairs和pairs的区别? 链接: link.

qq_21407523的博客 2万+

static 的三种用法:C 语言里一个关键字的三张面孔

本文系统讲解 C 语言中 static 关键字的三种用法:修饰局部变量延长生命周期、修饰全局变量与函数限制作用域到本文件。通过一个包含三个文件的完整工程示例对照演示,并从存储期、作用域与链接性三个属性解释其统一原理,最后补充单元测试框架偏爱 static 函数的工程实践。

大模型全栈工程师 · Thanks_ks 312

如何使用freesurfer对T1w结构像进行分区指标的提取?——皮层面积,灰质体积,平均厚度,厚度标准差,平均曲率、高斯曲率、曲率指数、折叠指数

如何使用freesurfer对T1w结构像进行分区指标的提取?——皮层面积,灰质体积,平均厚度,厚度标准差,平均曲率、高斯曲率、曲率指数、折叠指数

从事脑科学核磁共振方法学研究,在Nature communications等权威期刊发表研究论文,熟练掌握磁共振处理方法和统计学方法,欢迎大家和我交流。 3787

基于YOLO26深度学习框架的智能停车场管理系统的算法研究实现方法

本文研究了基于YOLO26深度学习框架的智能停车场管理系统实现方法。系统采用CSPDarknet53作为主干网络,结合特征金字塔和注意力机制提升检测性能。通过数据预处理、模型训练和停车分析三个主要模块,实现了车位占用检测、车辆类型识别等功能。实验结果表明,该方法在检测精度和速度方面表现优异,为智能停车场管理提供了有效的技术解决方案。

一键难忘的博客 571

【FDE知识库】(1):AI 编程时代开发语言选型分析,云使用go,企业用java,算法python,底层c

AI 编程时代,开发语言选型需综合考量AI适配度、编译速度、跨平台与学习成本。Python以海量语料和即时执行成首选,适用于AI/ML与原型开发;TypeScript凭借类型系统与秒级构建,成为前端及应用层主流;Go以极速编译与统一风格,契合AI代理高效迭代需求。Rust/C++虽性能强,但编译慢、学习成本高,不适于快速试错。综合推荐:优先选Python、TypeScript、Go,兼顾效率与生态,实现最优AI协作体验。

freewebsys的专栏 519

A*搜索算法在三维路径规划(避障)中的MATLAB实现与Python实现

A star algorithmA*搜索算法简介A*搜索算法的Python简化代码MATLAB实现启发函数回溯轨迹RRT算法对比A\*算法在三维路径规划中的一些不足 A*搜索算法简介 A*搜索算法是Greedy Best-First算法的改进,因为Greedy Best-First算法只考虑将预估距离(当前节点到目标点的预估距离)作为遴选开节点集的条件。即: priority=heuristic(goal,next)priority=heuristic(goal, next)priority=heurist

ZYunfei的博客 2万+
上一篇: 【路由交换技术】基于eNSP的多子网路由互通实验:从配置到验证的全流程指南
下一篇: 【C语言】第六课 联合体(Union)和位域(Bit-field)
jiaway
博客等级 码龄11年 39粉丝 92原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值