最近在认真学习C++基础,就此对于结构体的内存对齐做个学习笔记
(1)为什么需要内存对齐?
《windows核心编程》里这样说:CPU访问对齐数据时候效率最高,当数据大小的数据模数为0的时候,内存是对齐的。内存对齐牺牲空间换来更快的效率。
(2)如何去查看结构体内存结构?
IDE:VS2013 在创建项目中,选择某个.cpp文件,右键——>Properties——>Configuration Properties——>C/C++——>Command Line在右边的Additional Options中添加-d1reportSingleClassLayoutXXX (XXX代表类名),对项目进行built ,在output中可以找到类或者结构体的内存布局。
(3)成员变量对齐原理
VS2013默认以8字节对齐,对于32位平台,默认以4字节对齐,64位平台,默认按照8字节对齐,我的测试环境默认8字节对齐。通过#pragma pack(X)可以控制对齐
首先我们来看以下结构体:
struct S1
{
long long1;
int int1;
short short1;
double double1;
char char1;
};//Size = ?
struct S2
{
long long1;
int int1;
double double1;
short short1;
char char1;
};//Size = ?
大家可计算一下自己是否计算正确。
①.结构体中成员以8字节对齐,且对齐地址为偶数。
比如S1中long1+int1 = 8字节,short1 是2字节但是double1是8字节所以short1后填充6字节,尾部一个char1填充7字节。S2中尾部short1 和 char1分别于16,18偏移对齐,尾部填充5字节组成8字节。
②.合理安排结构体中成员位置,可以减少存储占用量。
我们再来看以4字节对齐:
#pragma pack(4)
struct S1
{
long long1;
int int1;
short short1;
double double1;
char char1;
};//Size = ?
struct S2
{
long long1;
int int1;
double double1;
short short1;
char char1;
};//Size = ?
#pragma pack(4)按照4字节对齐
由上可知,结构体成员布局总是以某字节为单位的,若成员大小不足则填充,并且成员偏移总是偶数。
结构体和联合体的对齐:
union U
{
char a[30];
long b;
char c[50];
int d;
};
struct S
{
char a[30];
long b;
char c[50];
int d;
};
由上可知:联合体U中,c占50个字节,但是联合体大小并非50,根据字节对齐原则,那么是否大小应该是56呢?并不是,因为其后的int类型4字节和c占用同一段。
内存结构:c |<- 2字节 ->| d 总共是8字节。所以U的大小是50 + 2 = 52
下面的S按照字节对齐原则得出,S的大小是30+2+4+50+2+4 = 92
附带如何求结构体成员的偏移:
#define OFFSET( struc, e ) (size_t)&(((struc*)0)- >e)
将0强制转换成结构体指针指向的地址,再进行取地址操作得到成员e相对0的地址,(size_t)转换成偏移量
关于内存对齐的探究就到这里啦!