[C++]内存对齐
[C++]内存对齐
不同类型的内存大小
| 数据类型 | 32位大小 | 64位大小 |
|---|---|---|
| char | 1 | 1 |
| short | 2 | 2 |
| int | 4 | 4 |
| long | 4 | 8 |
| long long | 8 | 8 |
| 指针 | 4 | 8 |
| float | 4 | 4 |
| double | 8 | 8 |
对齐规则
编译器有一个#pragma pack(n)表示默认对齐单位,实际进行结构体对齐时,会取n和成员中最长的数据类型的长度作为对齐单位,具体规则如下:
- 第一个成员变量的偏移量为 0。
- 其他成员变量的地址必须是其大小和对齐单位中较小值的整数倍。
- 结构体总大小必须是最大对齐单位的整数倍。
- 如果结构体中嵌套了其他结构体,嵌套结构体的起始地址也需要满足其最大对齐单位的整数倍。
例子
#pragma pack(4) // 默认对齐值
struct A
{
char x; // 占用地址0
int y; // 偏移量必须是4的整数倍,因此占用地址4567
char z; // 占用地址8,为了满足结构体大小为4的整数倍,地址9、10、11也算作A的内存
}; // 大小为12
struct B
{
char x; // 0
int *p; // 64位下大小为8,因此起始地址为8
int y; // 16
}; // 大小为24
struct C
{
int x; // 0
B b; // 这里看B的最大对齐值,为8,所以起始地址为8,占用24字节
char c; // 32
}; // 大小应该为8的整数倍,所以是40
类的内存对齐
class B
{
protected:
char x; // 0
int *p; // 64位下大小为8,因此起始地址为8
int y; // 16
public:
B() : x('0'), p(nullptr), y(0) {}
void Foo()
{
return;
}
}; // 这个类没有虚函数,对齐方式与结构体相同,大小为24
class B
{
protected:
char x; // 0
int *p; // 64位下大小为8,因此起始地址为8
int y; // 16
public:
B() : x('0'), p(nullptr), y(0) {}
void Foo()
{
return;
}
virtual void Bar() = 0; // 加上虚函数后,起始地址存的是虚函数表
}; // 大小为32
class C
{
protected:
char x; // 起始地址为8
public:
virtual void Bar()
{
// do nothing
return;
}
};
// 相当于struct C {void ** vtable; char x;};
// 对齐单位是8,所以大小为16

浙公网安备 33010602011771号