一、概述
C++空类或结构体的内存大小为1字节,为了保证其对象拥有彼此独立的内存地址。
非空类的大小与类中非静态成员变量和虚函数表的多少有关。
静态成员变量存储在全局数据区,不占用类或结构体的内存,使用sizeof获取的是类或结构体的内存大小时不包含静态成员变量。
而值得注意的是,类中非静态成员变量的大小与编译器内存对齐的设置有关。
成员变量在类中的内存存储并不一定是连续的。它是按照编译器的设置,按照内存块来存储的,这个内存块大小的取值,就是内存对齐。
二、
1、相关概念:偏移地址(offset),对齐参数(#pragma pack(n)),数据类型大小
2、规则
a、第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。
b、在数据成员完成各自对齐之后,类(结构或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。
很明显#pragma pack(n)作为一个预编译指令用来设置多少个字节对齐的。值得注意的是,n的缺省数值是按照编译器自身设置,一般为8,合法的数值分别是1、2、4、8、16。
即编译器只会按照1、2、4、8、16的方式分割内存。若n为其他值,是无效的。
#pragma pack(4) //设置下面结构体对齐参数为4
struct A
{
int a;
char b;
double c;
bool d;
};
#pragma pack //恢复默认对齐参数
#pragma pack(push) // 保存当前的对齐参数
#pragma pack(4) // 设置对齐参数为4
struct A {
int a;
char b;
double c;
bool d;
};
#pragma pack(pop) // 恢复上面保存的对齐参数
三、分析
以上面的结构体A为例
a为int型4字节和设置的对齐参数4相等,对齐参数取4,相对于结构体首地址偏移(offset)0,占4字节
b为char型1字节小于对齐参数4,对齐参数取1,相对于a地址偏移0,占1字节
c为double型4字节等于对齐参数4,对齐参数取4,相对于b偏移4字节(b占用1字节后面空出3字节),占4字节
d为bool型1字节小于对齐参数4,对齐参数取1,相对于c偏移0字节,占1字节,
结构体整体需满足对齐(结果体中最大变量长度4字节的整数倍),d占用1字节后面空3字节,结构体共占16字节
思考个问题:
假设类A里最长的成员变量长度为x,为了让类满足对齐,在类的最后一个成员变量后填补的字节数为y,那么x<=y这种情况存在吗?
我感觉填补的字节数y只会小于最长成员变量长度x。
4238

被折叠的 条评论
为什么被折叠?



