class A { public: int a; char b; int c; };
我看到每个编译器(对于x86,32或64位)为类A分配12个字节,而不是9.因此,它们将b对齐到您可以说的整数边界或总线边界.我的问题是,如果这是C标准,并且如果有任何编译器不这样做.
解决方法
>对象具有对齐要求,其大小为多个(因此,如果int为4个字节宽,则需要对齐1,2或4个字节,具体取决于实现).
>成员对象(如果它们没有被访问说明符分隔,例如public)都按它们声明的顺序分配
>并且他们被分配尊重他们的对齐要求.
所以不,标准并没有准确地说该类的大小应该是12个字节.
但确实说b应该在a之后分配,并且c应该在b之后分配.
在int为4字节宽且需要4字节对齐的平台上,这将留下12个字节作为最小有效大小:
> a占用前4个字节
> b占用一个字节
> c需要4个字节,但必须在4字节边界上分配. b通过这样的边界结束了一个字节,因此通过插入3个字节的填充来找到放置c的下一个有效位置.
所以类的总大小最终是成员的大小(4 1 4 = 9)加上三个字节的填充,总共12个.
还有另一条规则在这里没有效果,但是如果您已经按照a,c,b的顺序定义了成员,则这很重要.
包含类(A)从严格对齐的成员对象继承对齐要求.也就是说,因为它包含一个int,所以它具有与int相同的对齐要求.并且因为对象的总大小必须是其对齐要求的倍数,所以包含a,b,c顺序的成员的类仍然需要12个字节的存储空间.它只是将3个字节的填充转移到类的末尾,而不是在b和c之间.
但是,在某些其他情况下,按大小降序重新排序成员有时可以减小类的大小.
假设我们有一个这样的类:
class B { char a; double b; int c; };
这将需要24个字节的存储空间(1个字节用于a,8个字节用于b,4个字节用于c,但是为了确保b最终在8字节边界上,我们需要在a和7之间填充7个字节b,并且为了确保整个类的最大大小为8的倍数,我们需要在c之后另外4个字节.
但是根据大小重新排序成员,如下所示:
class B { double b; int c; char a; };
导致类只需要16个字节:
对于成员对象本身来说,相同的1 4 8个字节,但是现在c已经在4字节边界上对齐(因为它出现在b之后,以8字节边界结束),并且从不需要任何对齐,所以只有我们需要的对齐方式是确保B的大小为8的倍数.成员占用13个字节,因此我们可以添加3个字节的填充,类最终为16个字节,比第一个版本小33%.