细节:
我想知道什么规则用于确定一个类将使用多少内存,以及内存如何对齐.
例如,以下代码声明了4个类.前2个都是16个字节.但是3是48字节,即使它包含与前2个相同的数据成员.而第四个类与第三个数据成员具有相同的数据成员,只有不同的顺序,但它是32个字节.
#include <xmmintrin.h> #include <stdio.h> class TestClass1 { __m128i vect; }; class TestClass2 { char buf[8]; char buf2[8]; }; class TestClass3 { char buf[8]; __m128i vect; char buf2[8]; }; class TestClass4 { char buf[8]; char buf2[8]; __m128i vect; }; TestClass1 *ptr1; TestClass2 *ptr2; TestClass3 *ptr3; TestClass4 *ptr4; int main() { ptr1 = new TestClass1(); ptr2 = new TestClass2(); ptr3 = new TestClass3(); ptr4 = new TestClass4(); printf("sizeof TestClass1 is: %lu\t TestClass2 is: %lu\t TestClass3 is: %lu\t TestClass4 is: %lu\n",sizeof(*ptr1),sizeof(*ptr2),sizeof(*ptr3),sizeof(*ptr4)); return 0; }
我知道答案与课程数据成员的对齐有关.但是我正在试图明白这些规则是什么,以及在编译步骤中如何应用这些规则,因为我有一个类具有__m128i数据成员,但是数据成员不是16字节对齐,这导致了一个segfault,当编译器使用movaps生成代码来访问数据.
解决方法
>结构中的每个成员有一些大小和一些对齐要求a.@H_502_17@>编译器以大小S设置为零并将对齐要求A设置为一(字节)开始.@H_502_17@>编译器按顺序处理结构中的每个成员:
考虑会员的对齐要求a.如果S当前不是a的倍数,则只添加足够的字节S,以便它是a的倍数.这决定了会员将去哪里;它将从结构的开头(对于S的当前值)到偏移量S.@H_502_17@>将A设置为A和a的最小公倍数.@H_502_17@>将s添加到S,为会员留出空间.
>当对每个成员进行上述过程时,请考虑结构的对齐要求A.如果S当前不是A的倍数,则只需将其添加到S中,使其为A的倍数.
上述结构的大小是S的值.
另外:
>如果任何成员是数组,它的大小是元素的数量乘以每个元素的大小,其对齐要求是元素的对齐要求.@H_502_17@>如果任何一个成员是一个结构,其大小和对齐要求如上所述计算.@H_502_17@>如果任何成员是一个联盟:
>将S设置为最大成员的大小.@H_502_17@>将A设置为所有成员对齐的最小公倍数.@H_502_17@>如果S不是A的倍数,只需加上S,使其成为A的倍数.
考虑你的TestClass3:
> S从0开始,A从1开始.@H_502_17@> char buf [8]需要8个字节和对齐1,所以S增加8到8,A保持1.@H_502_17@> __m128i vect需要16个字节和对齐16.首先,S必须增加到16以给出正确的对齐.那么A必须增加到16.然后S必须增加16以为vect空间,所以S现在是32.@H_502_17@> char buf2 [8]需要8个字节和对齐1,所以S增加8到24,A保持16.@H_502_17@>最后,S是24,这不是A(16)的倍数,所以S必须增加8到32.
所以TestClass3的大小是32字节.
对于基本类型(int,double等),对齐要求取决于实现,主要由硬件决定.在许多处理器上,当数据具有一定的对齐方式(通常在内存中的地址是其大小的倍数)时,加载和存储数据的速度更快.除此之外,上述规则大部分来自逻辑;他们将每个成员放在必须满足对齐要求的地方,而不需要占用更多的空间.