编译器对齐机制——由一道求C++类大小的题说开
2016-01-19 18:43
405 查看
有如下代码段,问32位下sizeof(a)是多少
难点集中在union的大小,取最大应该是13,而不是16。
16是怎么来的,是对齐机制,巧就巧在这个对齐上,如果如题中所示,那么它的大小是16
如果没有那个int,又会是多少?
但是,其实这个结果是可变的,上边的都是gcc/g++自动出的结果,其实是可以手动改的。用#pragma pack(1)改对齐为1,结果就
这样一来,结果就不是24了,而是21。
结论就是,同一个联合体(结构体其实也一样)内,char本来是1对齐,碰到int就变成了4对齐,经测试(32位,g++/gcc),double也是4对齐,short是2对齐,反正都是要随那个宽的变。这个“碰到”在一个结构体或联合体内是不分先后的,先int还是后int,最后sizeof()结果都一样。
但是#pragma pack是分先后的,即时生效,什么时候设置,在那后边就全是设置的值。如下
所以说,那个题不严谨,他只展现了一部分,而不是整个带main的程序,如果真的放在一个大工程下,如果事先有主动设置的对齐值,结果就不一样了(pack参数也可以是2或者4)。
最后,自定义完了别忘了#pragma pack()恢复默认值,以免影响后边的类定义。
PS:编译器的个性化的东西很多,不属于语言本身,比如,同样是空结构体和联合体,用g++看zieof()结果就是1,而gcc看就是0,有的编译器可能干脆不让你编译通过,以提醒你那是空的,不过空的也有空的用处,内存占位——stub(桩)
class A { int i; union U { char buff[13]; int i; }u; void foo(){} typedef char* (*f)(void*); enum{red,green,blue}color; }a;结果是24,原因,int i占4字节,union U u占16字节,枚举值color占4字节。
难点集中在union的大小,取最大应该是13,而不是16。
16是怎么来的,是对齐机制,巧就巧在这个对齐上,如果如题中所示,那么它的大小是16
union U { char buff[13]; int i; }u;
如果没有那个int,又会是多少?
union U { char buff[13]; }u;其实这时候就是13了,可以看到这个对齐是遇到int才出现的。
但是,其实这个结果是可变的,上边的都是gcc/g++自动出的结果,其实是可以手动改的。用#pragma pack(1)改对齐为1,结果就
#pragma pack(1) class A { int i; union U { char buff[13]; int i; }u; void foo(){} typedef char* (*f)(void*); enum{red,green,blue}color; }a;
这样一来,结果就不是24了,而是21。
结论就是,同一个联合体(结构体其实也一样)内,char本来是1对齐,碰到int就变成了4对齐,经测试(32位,g++/gcc),double也是4对齐,short是2对齐,反正都是要随那个宽的变。这个“碰到”在一个结构体或联合体内是不分先后的,先int还是后int,最后sizeof()结果都一样。
但是#pragma pack是分先后的,即时生效,什么时候设置,在那后边就全是设置的值。如下
class A { int i; union U { char buff[13]; int i; }u; #pragma pack(1) char buff[13]; void foo(){} typedef char* (*f)(void*); enum{red,green,blue}color; }a;sizeof(a)结果是37,后边这个buff[13]是1对齐,前边那个buff[13]依然是4对齐!!!
所以说,那个题不严谨,他只展现了一部分,而不是整个带main的程序,如果真的放在一个大工程下,如果事先有主动设置的对齐值,结果就不一样了(pack参数也可以是2或者4)。
最后,自定义完了别忘了#pragma pack()恢复默认值,以免影响后边的类定义。
PS:编译器的个性化的东西很多,不属于语言本身,比如,同样是空结构体和联合体,用g++看zieof()结果就是1,而gcc看就是0,有的编译器可能干脆不让你编译通过,以提醒你那是空的,不过空的也有空的用处,内存占位——stub(桩)
相关文章推荐
- Android Native 绘图方法
- C#中struct和class的区别详解
- VBS ArrayList Class vbs中的数组类
- 大家看了就明白了css样式中类class与标识id选择符的区别小结
- C#中sizeof的用法实例分析
- 浅析C语言中的sizeof
- 深入sizeof的使用详解
- C语言中的sizeof操作符用法及和strlen的区别
- sizeof()的简单介绍
- 深入了解PHP类Class的概念
- jquery 表单验证之通过 class验证表单不为空
- setAttribute 与 class冲突解决
- JavaScript中的类(Class)详细介绍
- javascript面向对象包装类Class封装类库剖析
- 详解js中class的多种函数封装方法
- jQuery使用hide方法隐藏指定元素class样式用法实例
- jQuery给多个不同元素添加class样式的方法
- jQuery点击改变class并toggle及toggleClass()方法定义用法
- C语言中sizeof()与strlen()函数的使用入门及对比
- 基于Sizeof与Strlen的区别以及联系的使用详解