内存对齐
内存对齐是一种为了提高内存访问效率而进行的数据存储方式。其基础规则如下:
- 顺序分配:按照声明顺序为结构体中的变量分配内存。
- 内存对齐要求:每个变量在结构体中的位置应该是该变量类型大小的整数倍。如果不是,就需要填充空位,直到满足对齐要求。
- 结构体大小:整个结构体的大小必须是其内部最大变量类型大小的整数倍。这可能会在结构体结尾处增加额外的填充。
使用 #pragma pack(n)
可以修改对齐规则:
- 偏移量对齐要求:偏移量应该是当前变量大小和
n
中较小者的整数倍。 - 结构体大小对齐要求:结构体总大小应该是
n
和最大变量类型大小中较小者的整数倍。 - n的值要求:
n
必须为1、2、4、8等2的幂次,如果不是这些值,会采用默认对齐规则。
示例代码
以下是一个结构体示例及其内存对齐情况:
#include <iostream>
#pragma pack(push, 1) // 1字节对齐
struct PackedStruct {
char a; // 1字节
int b; // 4字节
short c; // 2字节
};
#pragma pack(pop)
struct RegularStruct {
char a; // 1字节
int b; // 4字节
short c; // 2字节
};
int main() {
std::cout << "Size of packed struct: " << sizeof(PackedStruct) << " bytes\n";
std::cout << "Size of regular struct: " << sizeof(RegularStruct) << " bytes\n";
return 0;
}
解释:
无对齐规则(RegularStruct):
char a
需要1个字节。- 然后
int b
必须从4的倍数地址开始(因为int
四字节对齐),所以后面空出3个字节。 short c
需要从2的倍数地址开始(因为short
两字节对齐),因此不需要额外的填充字节。
内存分布:
| a (1 byte) | padding (3 bytes) | b (4 bytes) | c (2 bytes) | padding (2 bytes) |
总大小是 1 + 3 + 4 + 2 = 10
字节,再加上尾部填充,总大小为12字节,因为 int
是其中最大的类型,占4字节,必须是其整数倍。
1字节对齐(PackedStruct):
在 #pragma pack(1)
下,不使用默认对齐规则,每个成员紧密排列:
| a (1 byte) | b (4 bytes) | c (2 bytes) |
总大小是 1 + 4 + 2 = 7
字节。
结果输出:
Size of packed struct: 7 bytes
Size of regular struct: 12 bytes
这个例子展示了内存对齐的差异,对于特定应用场景,选择合适的对齐方式可以显著提升性能或减少内存占用。