一江春水向东流

做一个有思想的人,期待与每一位热爱思考的人交流,您的关注是对我最大的支持。

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  44 随笔 :: 139 文章 :: 81 评论 :: 0 Trackbacks
#pragma pack() struct test { char m1; double m4; int m3; }; #pragma pack() #pragma pack(8) struct A { int n; char c; short s; }; struct B { char c; int n; short s; }; #pragma pack() sizeof test:16 sizeof a:8 sizeof b:12 编译器默认的成员对齐值是8字节,通过#pragma pack(show)指令,编译的时候在输出栏会限制默认对齐值。以上程序运行完通过调试的内存察看功能得到a和b的内存存储区域如下: a的存储区域:0x0012FED0 02 00 00 00 31 00 03 00 b的存储区域:0x0012FEBC 31 00 00 00 02 00 00 00 03 00 00 00 最前面的4字节整数是变量的起始地址,后面是变量的整个存储区域。 现在我们按照 align of member = min( pack setting value, sizeof(member) )的公式分析一下a和b的存储。 a的第一个成员n为int,大小为4,align of a.n = min(8,sizeof(int) ),对齐值为4。第一个成员相对于结构体起始地址从0偏移开始,前四个字节02 00 00 00即为n的存储区域,因为x86是Little Endian(低字节在前)的字节顺序,所以第一字节是2,后面三个字节0,我们通常写成0x00000002; a的第二个成员c为char,大小为1,align of a.c=min(8,sizeof(char)),对齐值为1。c紧接着a后面存储从偏移4开始,满足1字节对齐的要求。它的值为'1',ASCII码为0x31,共一个字节31; a的第三个成员为short,大小为2,align of a.s=min(8,sizeof(short)),对齐值为2。如果紧接第二个成员从偏移5开始存储就不满足2字节对齐,因此跳过1个字节,从偏移6字节的地方开始存储,即最后两个字节03 00; b的第一个成员c为char,大小为1,align of a.c=min(8,sizeof(char)),对齐值为1。第一个成员从偏移起始地址0字节开始存储,它的值为'1',ASCII码为0x31,共一个字节31; b的第二个成员n为int,大小为4,align of a.n = min(8,sizeof(int) ),对齐值为4。如果紧接第二个成员后面从偏移1开始存储就不能4字节对齐,因此跳过3个字节,从偏移4字节的地方开始存储,即第5-8的四个字节02 00 00 00; b的第三个成员为short,大小为2,align of a.s=min(8,sizeof(short)),对齐值为2。紧接第二个成员从偏移8字节的地方开始存储,即9-10两个字节03 00; 这时有人可能要问,b为什么最后多了两个字节00 00呢?这就是我们下面要讲的,整个结构体的对齐。 2、align指令 align指令可以用于设置各种内置类型、自定义类型如struct、union或class的的对齐方式。指令格式为:__declspec(align(#)) ,#是对齐值,取值为2的1次方至2的8192次方。在声明自定义类型或内置变量时,如果指定了对齐值,则对应变量的起始地址必须是该值的整数倍。除此外,它还会影响结构体的大小。下面引用两段MSDN关于align的描述: Without __declspec(align(#)), Visual C++ aligns data on natural boundaries based on the size of the data, for example 4-byte integers on 4-byte boundaries and 8-byte doubles on 8-byte boundaries. Data in classes or structures is aligned within the class or structure at the minimum of its natural alignment and the current packing setting (from #pragma pack or the /Zp compiler option). 从这段可以看出,如果没有设置align(#)值,变量x按照sizeof(x)来对齐起始地址。类或结构体内的成员在类或结构体内部按照min( pack setting value,sizeof(member))来对齐。这个我们在pack指令部分已经分析过。 The sizeof value for any structure is the offset of the final member, plus that member's size, rounded up to the nearest multiple of the largest member alignment value or the whole structure alignment value, whichever is greater. 从这段可以看出,align(#)指令会影响结构体或类的大小。总结公式为: sizeof(structure) = (结构体最后一个成员的偏移 + sizeof(结构体最后一个成员) ) 上取整 ( n* max( 结构体各成员的对齐值,align(#)设置的值 ) ); 其中n为正整数。 根据该公式我们分析一下b为什么后面会多两个填充字节0。 b的最后一个成s偏移为8,大小为2,b中各成员对齐值最大的为4,因为未设置align(#),所以上取整的数值为4n。8+2按4的倍数上取整为12。因此后面需要填充两个字节,这样才能使sizeof(b) == 12。
posted on 2012-06-05 18:00 allic 阅读(364) 评论(0)  编辑  收藏 所属分类: C/C++

只有注册用户登录后才能发表评论。


网站导航: