默认情况下,每个成员相对于结构体变量地址的偏移量正好是该成员类型所占字节的整数倍;且最终占用字节数为成员类型中最大占用字节数的整数倍。
struct A {
int a;
char b;
short c;
};
A的大小为4+1+1(填充)+2=8
a的偏移量为0,占据4个字节。b的偏移量为4,占据1个字节。c的偏移量为6,占据2个字节。
struct B {
char a;
char b;
char c;
};
B的大小为1+1+1+1(填充)=4
a的偏移量为0,占据1个字节。b的偏移量为1,占据1个字节。c的偏移量为2,占据1个字节。
struct C {
char b;
int a;
short c;
};
C的大小为1+3(填充)+4+2+2(填充)=12
a的偏移量为0,占据1个字节。b的偏移量为4,占据4个字节。c的偏移量为8,占据2个字节。
#pragma pack(2)
struct D {
char b;
int a;
short c;
};
pragma pack(2)指明2字节对齐。则整体为2的整数倍。
D的大小为1+1(填充)+4+2=8
a的偏移量为0,占据1=2个字节。b的偏移量为2,占据4个字节。c的偏移量为6,占据2个字节。
struct A {
int a;
char b;
short c;
};
struct B : A {
char c;
int d;
short e;
};
当发生继承时,基类的算基类,其后填充不能被占用;子类算子类。
为什么需要字节对齐?
当CPU访问正确对齐的数据时,它的运行效率最高,当数据大小的数据模数的内存地址是0时,数据是对齐的。例如:WORD值应该是总是从被2除尽的地址开始,而DWORD值应该总是从被4除尽的地址开始。
数据对齐不是内存结构的一部分,而是CPU结构的一部分。当CPU试图读取的数值没有正确的对齐时,CPU可以执行两种操作之一:产生一个异常条件;执行多次对齐的内存访问,以便读取完整的未对齐数据,若多次执行内存访问,应用程序的运行速度就会慢。
C++类中的数据成员
1.在不考虑(或者说在没有)虚函数和虚继承的情况下,sizeof(自定义类)也按照类似上面的方式来计算。
2.如果一个类拥有虚函数或者虚继承,则在数据成员的基础上相当于多一个指针类型的数据成员(位置在所有数据成员的前面),最后计算时加上即可。
3.如果一个类或者结构体不含有任何数据成员,且无虚函数以及虚继承,则sizeof()结果为1。
4.静态成员不在计算范围。
class S {
};
// size = 1
class S {
S() {}
~S() {}
};
// size = 1
class S {
S() {}
~S() {}
int a;
};
// size = 4
class S {
S() {}
~S() {}
virtual void fun() {}
int a;
};
// size = 8