知识补全-什么是内存对齐
**内存对齐是指数据在内存中的存放地址必须是某个数(通常是2的幂次方,如4、8、16字节)的整数倍。**
为什么需要内存对齐?
**1. 硬件访问效率**
- CPU 从内存读取数据是按"字长"(如64位机器是8字节)一块一块读的
- 如果数据跨边界存放,CPU可能需要读两次才能拿到完整数据
- 对齐后一次读取就能搞定,效率更高
**2. 某些平台强制要求**
- 部分CPU(如ARM、SPARC)访问未对齐数据会直接报错或性能暴跌
- x86/x64 宽容一些,但未对齐访问仍然慢
举个例子
假设有一个结构体:
```c
struct Example {
char a; // 1字节
int b; // 4字节
char c; // 1字节
};
```
没有对齐时(理想化):1 + 4 + 1 = 6字节
实际对齐后:
```
| a | padding | b | c | padding |
1 3 4 1 3
```
总共12字节。b 需要从4的倍数地址开始,所以 a 后面补了3字节;整个结构体大小也要是最大成员对齐值(4)的倍数,所以 c 后面也补了3字节。
```
// 未对齐:int在地址0x01
// CPU需要读取两次:先读0x00-0x03,再读0x04-0x07,然后拼凑
// 对齐后:int在地址0x04
// CPU一次就能读取0x04-0x07
```
**常见对齐规则**
```
数据类型 32位系统 64位系统
char 1字节 1字节
short 2字节 2字节
int/float 4字节 4字节
long/double/指针 4字节 8字节
```
实际影响
- 结构体大小变大 — padding 浪费了空间
- 数组访问更高效 — 元素对齐,CPU读取更快
- 跨平台移植 — 不同平台对齐规则不同,同样的结构体大小可能不一样
如何控制?
```c
#pragma pack(1) // 按1字节对齐,取消padding
struct Example {
char a;
int b;
char c;
};
#pragma pack() // 恢复默认对齐
// 此时 sizeof(Example) = 6
```
或者用 `__attribute__((packed))`(GCC)。
简单说:内存对齐就是用空间换时间,让CPU读数据更快更省事。