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

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

目 录


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

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

1)分析讲解

一切的根本原因是:

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

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

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

内存对齐规则:

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

比如在 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) 必须是一个"安全步长",这个步长必须能保证下一个结构体实例的起始地址,仍然满足其内部所有成员的对齐约束。而这个"安全步长"的最小值,就是 结构体中最大成员的对齐要求 ,也就是结构体的大小,必须是占内存最大成员的整数倍。为了达到这个效果,编译器会在结构体尾部填充字节。

以如下结构体为例:

c 复制代码
struct BadStudent
{
	char grade;		// 1字节
	int id;			// 4字节
	char gender;	// 1字节
};

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

缺点及优化方法:

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

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

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

c 复制代码
struct BadStudent
{
	int id;			// 4字节
	char grade;		// 1字节
	char gender;	// 1字节
};

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

2)总结

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

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

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

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


相关推荐
北风toto12 分钟前
KMP 算法详解:从暴力匹配到 O(n+m) 的字符串搜索
java·开发语言·算法
william_yangshun13 分钟前
WordCraft 观察:纯 Rust 重写文字处理器,把文档变成可编程对象
开发语言·后端·rust·文档自动化
沫璃染墨14 分钟前
《从零入门数据结构与算法(二):线性表详解——从顺序表原理到静态与动态实现》
c语言·数据结构·顺序表
dtq042416 分钟前
C++ - 变量
开发语言·c++
撸串-研究生19 分钟前
面向景区的综合服务管理平台设计——以稻城亚丁景区为例【附源码】
java·开发语言·vue.js·前后端分离·稻城亚丁景区
wuyk55519 分钟前
样章-第03讲-FreeRTOS在16KB-RAM上的裁剪与陷阱
c语言·开发语言·stm32·单片机·嵌入式硬件·物联网·系统架构
爱读书的小胖19 分钟前
Codewars Sum of a Sequence Hard Core Version C 解题分析
c语言·数据结构·算法
霖霖71425 分钟前
【ESP32笔记】LED操作和呼吸灯实现
笔记·单片机·嵌入式硬件
kiros_wang26 分钟前
网络状态监听&WiFi信息获取:弱网提示、断网兜底方案
开发语言·网络·php
geovindu27 分钟前
rust: pool Pattern (续)
开发语言·后端·设计模式·rust·对象池简写模式