当前位置: 首页 > news >正文

单片机/C/C++八股:(十五)内存对齐、结构体内存对齐

上一篇下一篇
const 关键字的作用(和 define 比呢?)

目 录

  • 内存对齐、结构体内存对齐
    • 1)分析讲解
    • 2)总结

内存对齐、结构体内存对齐

视频教学连接:CPU 到底是怎么读内存的?十分钟搞懂内存对齐_哔哩哔哩_bilibili

1)分析讲解

一切的根本原因是:

CPU 从内存中读取数据,32 位系统一次会读取 32 位(4字节),64 位系统一次会读取 64 位(8字节),以 32 位系统为例:一次读 4 字节,就意味着从 0 地址开始的话,每次都会从 4 的整数倍地址处开始读。

所以为了保证读取效率和兼容性,数据存储的时候,会自动进行内存对齐,实现内存对齐的方式是在变量值之间填充字节(padding)

数据不进行内存对齐的话,就需要读取多次才能拼出完整的值:

内存对齐规则:

数据类型的大小,就是它的对齐边界(数据类型占n nn个字节,那么其起始地址就必须存放在n nn的倍数地址上)

比如在 32 系统中:

  • char 对齐边界:1字节(任意地址);
  • short 对齐边界:2字节(偶数地址);
  • int / float 对齐边界:4字节(4的倍数地址);
  • double 对齐边界:8字节(8的倍数地址)。

内存对齐是通用的 硬件/ABI 要求,不仅限于结构体,主要考察结构体内存对齐还有另一个原因⟶ \longrightarrow

结构体的特性:

结构体的大小,必须是占内存最大成员的整数倍。

核心原因:为了支持结构体数组的正确内存布局,确保结构体数组中每一个元素的起始地址都满足其内部成员的对齐要求,从而保证程序在所有平台上正确、高效运行。

具体来说:假设定义了一个结构体S,并声明一个数组:struct S arr[2];,结构体数组元素在内存中是紧挨着的,即&arr[1] == &arr[0] + sizeof(struct S),为了让arr[1]中的每个成员也依然满足对齐要求sizeof(struct S)必须是一个“安全步长”,这个步长必须能保证下一个结构体实例的起始地址,仍然满足其内部所有成员的对齐约束。而这个“安全步长”的最小值,就是结构体中最大成员的对齐要求,也就是结构体的大小,必须是占内存最大成员的整数倍。为了达到这个效果,编译器会在结构体尾部填充字节。

以如下结构体为例:

structBadStudent{chargrade;// 1字节intid;// 4字节chargender;// 1字节};

以为是 1+4+1=6 字节,实际上是 12 字节:先内存对齐到 1+(3)+4+1=9 字节 → 再填充字节到 int 型的整数倍 12 字节。

缺点及优化方法:

  • 缺点:内存对齐会导致填充字节无法使用,造成内存浪费。

  • 方法:结构体成员按数据类型从大到小排列(如果定义了一个 char 型的数组,那这个数组不用放在最前面,单个元素只是 char ,但数组长度可能会造成一定的影响)。

还以那个结构体为例,其元素换个顺序:

structBadStudent{intid;// 4字节chargrade;// 1字节chargender;// 1字节};

现在实际上占用 4+1+1=6 → 8 字节。

2)总结

内存对齐源于 CPU 根据系统位数按固定字长(如 4 或 8 字节)高效读取内存的机制,要求数据起始地址为其类型大小的整数倍。

内存对齐的规则:数据类型占n nn个字节,那么其起始地址就必须存放在n nn的倍数地址上(32/64位系统中,数据类型所占字节数不同)。

而为了确保结构体数组中每一个元素的起始地址都能满足其内部成员的对齐要求,所以结构体的大小,必须是占内存最大成员的整数倍

虽然内存对齐提高了 CPU 的访问效率,但会造成所填字节的浪费,所以为了节省空间,结构体成员最好要按数据类型从大到小排列


http://www.jsqmd.com/news/510792/

相关文章:

  • OpenClaw技能市场挖掘:Qwen3-32B加持的5个高效办公技能
  • VideoAgentTrek Screen Filter 助力在线教育:AI自动批改编程作业屏幕截图
  • Adeon嵌入式GSM短信远程控制固件框架
  • vLLM并行批量推理实战:提升大模型生成效率的关键技巧
  • 计算机网络知识应用:优化Z-Image-Turbo_Sugar脸部Lora分布式推理的节点通信
  • Qwen3-32B-Chat FP16/8bit/4bit量化对比实测:RTX4090D显存占用与推理速度分析
  • 基于SpringBoot的摄影毕业设计系统实战:从需求到部署的全链路实现
  • 深入解析fastboot:从原理到实战刷机指南
  • TVBoxOSC:开源电视盒子管理工具的技术革新与场景实践
  • 2026年AI圈薪资大揭秘:月薪7万只是起点?高薪岗位技能清单与涨薪秘籍全解析!
  • SecGPT-14B商业应用:云原生环境下网络安全知识引擎集成实践
  • OFA图像描述系统快速体验:上传风景、人物、物品图片,实测生成效果
  • Z-Image-Turbo_Sugar脸部Lora跨平台部署:在VMware虚拟机中配置Linux模型服务器
  • ABYSSAL VISION(Flux.1-Dev)开发工具链:Keil5工程管理与团队协作启示
  • 我的第一个多智能体项目踩坑实录:LangGraph连接Dify时,流式响应和错误处理怎么做?
  • GLM-4.7-Flash快速体验:Ollama一键部署,立即开始AI对话
  • 视频编解码技术入门:从YUV到H.265的实战解析
  • CogVideoX-2b一文详解:CSDN专用版核心功能深度解读
  • 普冉单片机实战入门:从零到点灯,成本十元内的32位MCU开发指南
  • 别再死记公式了!用Excel手把手带你算一遍神经网络的梯度更新(附可下载表格)
  • 突破Python量化瓶颈:fengwo模块精准复现筹码峰(COST/WINNER)与无缝调用通达信DLL实战
  • STM32CubeMX实战:串口通信与重定向的配置与优化
  • Dify Token成本可视化监控插件一键安装包(含K8s Helm Chart + Docker Compose双模式,仅限前500名开发者免费获取)
  • SakuraAlpha嵌入式物联网通信库详解
  • Python数据可视化利器-Matplotlib用法详解
  • 医学图像分析的终极利器:HoVer-Net核实例分割与分类完整指南
  • Android应用集成:在移动端调用Qwen-Image-Edit-F2P服务实现人像编辑
  • 单片机/C/C++八股:(十六)C 中 malloc/free 和 C++ 中 new/delete 有什么区别?
  • 无人机避障实战:Vins Fusion在NVIDIA Jetson Orin NX上的性能优化与避坑指南
  • 【fastadmin】实现批量导入Excel与自定义按钮管理管理员权限的实战指南