单片机/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 的访问效率,但会造成所填字节的浪费,所以为了节省空间,结构体成员最好要按数据类型从大到小排列


相关推荐
老约家的可汗2 小时前
C/C++内存管理探秘:从内存分布到new/delete的底层原理
c语言·c++
娇娇yyyyyy2 小时前
QT编程(13): Qt 事件机制eventfilter
开发语言·qt
bcbobo21cn2 小时前
C# byte类型和byte数组的使用
开发语言·c#·字节数组·byte类型
计算机安禾2 小时前
【C语言程序设计】第37篇:链表数据结构(一):单向链表的实现
c语言·开发语言·数据结构·c++·算法·链表·蓝桥杯
SUNNYSPY0012 小时前
65R380-ASEMI超结MOS管TO-252封装
单片机
阿贵---2 小时前
C++构建缓存加速
开发语言·c++·算法
紫丁香2 小时前
pytest_自动化测试3
开发语言·python·功能测试·单元测试·集成测试·pytest
bearpping2 小时前
java进阶知识点
java·开发语言
杰杰7982 小时前
Python面向对象——类的魔法方法
开发语言·python