struct union数据对齐和sizeof大小
2017-09-03 13:21
736 查看
什么是数据对齐?简单的说就是数据的起始地址必须是对齐值的整数倍。如果对齐值为N,则 起始地址 % N=0。
为什么要数据对齐?为了提高存取变量的效率。字节是内存空间分配的最小单位, 在程序中,我们定义的变量可以放在任何位置。其实不同架构 的CPU在访问特定类型变量时是有规律的,比如有的CPU访问int型变量时,会从偶数地址开始读取的,int类型占用4个字节(windows平台)。 0X0000,0X0004,0X0008…..这样只需要读一次就可以读出Int类型变量的值。相反地,则需要读取二次,再把高低字节相拼才能得到 int类型的值,这样子看的话,存取效率当然提高了。
通常写程序的时候,不需要考虑这些情况,编译都会为我们考虑这些情况,除非针对那些特别架构的 CPU编程的时候的则需要考虑 。当然用户也可以手工控制对齐方式。
数据对齐可以分为几种类别:
1 基本数据类型的数据对齐
基本类型的数据对齐值是其本身的大小。
2 struct/class的自身对齐值。对于结构体和类的自身对齐值是所有成员中最大的自身对齐值。
结构体和类的对齐规则:先将数据成员对齐,在将结构体和类自身对齐,最终大小与数据成员顺序 有关。
3 union的自身对齐值。union的自身对齐值是所有成员中最大的对齐值。union的对齐规则,只需要union自身对齐,不需要数据成员对齐,最终大小与数据成员顺序无关。
4 指定对齐值。使用#pragma pack(n)指定对齐值为n,使用#pragma pack() 回复默认对齐值。
5 有效对齐值。对于指定了对齐值的代码, 有效对齐值=min(类/结构体/成员的自身对齐值, 指定对齐值)
未指定对齐值时,默认的对齐值一般为8。
有效对齐值决定了数据存放的方式,sizeof运算符是根据有效对齐值计算大小的。
举例分析:
U1,U2,U3的sizeof的值都是16。 union的大小是所有成员中内存最大的大小。所以是9。因为对齐问题,union自身的对齐值是所有成员对齐的最大值 8。所以要填充 9个字节, 最终的大小为16。
从这个例子可以看出:union不需要成员数据对齐, 最终大小与成员的顺序无关。
结果值分别为16 20 16。
先看A,首先是成员的对齐。 a需要9个字节,char的对齐值是2,所以填充1个字节,9 + 1 + 2 = 12 个字节。int的对齐值为4,12 % 4 = 0,所以 大小为 12 + 4 = 16。在看 struct的对齐。struct的对齐值为最大对齐值4。 16 % 4 = 0。 最终大小为16。
在看B,首先是成员的对齐。short需要2字节,int的对齐值为4,所以填充2个字节,2 + 2 + 4 = 8。 char的对齐值为1(与数组无关,不是9), 8 + 9 = 17。再看struct的对齐值为4,填充3个字节,17 + 3 = 20。
再看C, int 需要4个字节, a 需要9个字节, 4 + 9 = 13。 short需要2个字节, 4 + 9 + 1 + 2 = 16。 再看struct的对齐,对齐值为4, 16 % 4 = 0。 最终结果为4。
从这个例子可以看出:struct需要先对其数据成员,在对其struct本身。最终大小与成员顺序有关。
书写结构体时,建议按照数据类型(对齐值)从小到大书写。
结果值分别为10 10 10 16 16 16.
先看三个union。大小都为9,成员中最大的对齐值为8,指定的对齐值为2, 有效对齐值为2。union本身对齐值为2。 则 结果为9+1=10。
再看A。a需要9个字节,short需要2个字节,填充一个字节,9+1+2= 12。int的对齐值为4,指定为2,有效对齐值为2。 所以 12+4 =16。再看结构体本身,成员最大对齐值为4,指定为2, 有效对齐值为2, 16 % 2 = 0。最终结果为 16。
再看B。short需要2字节,int有效对齐值为2,2 + 4 = 6, char需要9字节, 6+ 9=15。 再看struct本身对齐。有效对齐值为2, 15+ 1 = 16。
再看C。int 占4字节,数组占9字节, 4+ 9 = 13, 填充一个字节, 13+1 + 2 = 16. 再看struct本身对齐。满足要求。最终结果为16。
如果是嵌套的情况呢?
举例分析:
A B C最终大小为:32 40 48;
分析:根据前面的分析,union U的大小为16,对齐值为 8。
A: U大小为16, char数组大小为9, 16 + 9 = 25。填充1个字节,放short, 25 + 1 + 2 = 28。 再放int, 28+4=32。struct本身的对齐值为8, 32 % 8 = 0,满足要求。
B:short占2字节, U占16,最气质为8,所以填充6字节, 2 + 6 + 16 = 24。放int, 24 + 4 = 28。放char数组,28+9=37。 struct本身有效对齐值为8,填充3字节, 37+3 = 40.
C: A的大小为32, 有效对齐值为8。 int 占4字节, char数组占9字节,4 +9=13。填充一个字节,放short,13+1+2 = 16。 放A,16+32 = 48。struct本身对齐也满足。
总结:对于嵌套类型,先按照规则分别计算每个数据成员的大小和对齐值,在考虑结构体本身的对齐。
为什么要数据对齐?为了提高存取变量的效率。字节是内存空间分配的最小单位, 在程序中,我们定义的变量可以放在任何位置。其实不同架构 的CPU在访问特定类型变量时是有规律的,比如有的CPU访问int型变量时,会从偶数地址开始读取的,int类型占用4个字节(windows平台)。 0X0000,0X0004,0X0008…..这样只需要读一次就可以读出Int类型变量的值。相反地,则需要读取二次,再把高低字节相拼才能得到 int类型的值,这样子看的话,存取效率当然提高了。
通常写程序的时候,不需要考虑这些情况,编译都会为我们考虑这些情况,除非针对那些特别架构的 CPU编程的时候的则需要考虑 。当然用户也可以手工控制对齐方式。
数据对齐可以分为几种类别:
1 基本数据类型的数据对齐
基本类型的数据对齐值是其本身的大小。
类型 | 对齐值(字节) |
---|---|
char | 1 |
short | 2 |
int | 4 |
float | 4 |
double | 8 |
指针 | 4(32位) 8(64位) |
结构体和类的对齐规则:先将数据成员对齐,在将结构体和类自身对齐,最终大小与数据成员顺序 有关。
3 union的自身对齐值。union的自身对齐值是所有成员中最大的对齐值。union的对齐规则,只需要union自身对齐,不需要数据成员对齐,最终大小与数据成员顺序无关。
4 指定对齐值。使用#pragma pack(n)指定对齐值为n,使用#pragma pack() 回复默认对齐值。
5 有效对齐值。对于指定了对齐值的代码, 有效对齐值=min(类/结构体/成员的自身对齐值, 指定对齐值)
未指定对齐值时,默认的对齐值一般为8。
有效对齐值决定了数据存放的方式,sizeof运算符是根据有效对齐值计算大小的。
举例分析:
union U1 { char a[9]; int b; double c; }; union U2 { int b; char a[9]; double c; }; union U3 { double c; int b; char a[9]; };
U1,U2,U3的sizeof的值都是16。 union的大小是所有成员中内存最大的大小。所以是9。因为对齐问题,union自身的对齐值是所有成员对齐的最大值 8。所以要填充 9个字节, 最终的大小为16。
从这个例子可以看出:union不需要成员数据对齐, 最终大小与成员的顺序无关。
struct A { char a[9]; short b; int c; }; struct B { short b; int c; char a[9]; }; struct C { int c; char a[9]; short b; };
结果值分别为16 20 16。
先看A,首先是成员的对齐。 a需要9个字节,char的对齐值是2,所以填充1个字节,9 + 1 + 2 = 12 个字节。int的对齐值为4,12 % 4 = 0,所以 大小为 12 + 4 = 16。在看 struct的对齐。struct的对齐值为最大对齐值4。 16 % 4 = 0。 最终大小为16。
在看B,首先是成员的对齐。short需要2字节,int的对齐值为4,所以填充2个字节,2 + 2 + 4 = 8。 char的对齐值为1(与数组无关,不是9), 8 + 9 = 17。再看struct的对齐值为4,填充3个字节,17 + 3 = 20。
再看C, int 需要4个字节, a 需要9个字节, 4 + 9 = 13。 short需要2个字节, 4 + 9 + 1 + 2 = 16。 再看struct的对齐,对齐值为4, 16 % 4 = 0。 最终结果为4。
从这个例子可以看出:struct需要先对其数据成员,在对其struct本身。最终大小与成员顺序有关。
书写结构体时,建议按照数据类型(对齐值)从小到大书写。
#pragma pack(2)
union U1 { char a[9]; int b; double c; }; union U2 { int b; char a[9]; double c; }; union U3 { double c; int b; char a[9]; };
struct A { char a[9]; short b; int c; }; struct B { short b; int c; char a[9]; }; struct C { int c; char a[9]; short b; };
结果值分别为10 10 10 16 16 16.
先看三个union。大小都为9,成员中最大的对齐值为8,指定的对齐值为2, 有效对齐值为2。union本身对齐值为2。 则 结果为9+1=10。
再看A。a需要9个字节,short需要2个字节,填充一个字节,9+1+2= 12。int的对齐值为4,指定为2,有效对齐值为2。 所以 12+4 =16。再看结构体本身,成员最大对齐值为4,指定为2, 有效对齐值为2, 16 % 2 = 0。最终结果为 16。
再看B。short需要2字节,int有效对齐值为2,2 + 4 = 6, char需要9字节, 6+ 9=15。 再看struct本身对齐。有效对齐值为2, 15+ 1 = 16。
再看C。int 占4字节,数组占9字节, 4+ 9 = 13, 填充一个字节, 13+1 + 2 = 16. 再看struct本身对齐。满足要求。最终结果为16。
如果是嵌套的情况呢?
举例分析:
union U { char a[9]; int b; double c; }; struct A { U u; char a[9]; short b; int c; }; struct B { short b; U u; int c; char a[9]; }; struct C { int c; char a[9]; short b; struct A aa; };
A B C最终大小为:32 40 48;
分析:根据前面的分析,union U的大小为16,对齐值为 8。
A: U大小为16, char数组大小为9, 16 + 9 = 25。填充1个字节,放short, 25 + 1 + 2 = 28。 再放int, 28+4=32。struct本身的对齐值为8, 32 % 8 = 0,满足要求。
B:short占2字节, U占16,最气质为8,所以填充6字节, 2 + 6 + 16 = 24。放int, 24 + 4 = 28。放char数组,28+9=37。 struct本身有效对齐值为8,填充3字节, 37+3 = 40.
C: A的大小为32, 有效对齐值为8。 int 占4字节, char数组占9字节,4 +9=13。填充一个字节,放short,13+1+2 = 16。 放A,16+32 = 48。struct本身对齐也满足。
总结:对于嵌套类型,先按照规则分别计算每个数据成员的大小和对齐值,在考虑结构体本身的对齐。
相关文章推荐
- C++中数据对齐问题。struct、union、enum,类继承。再谈sizeof()
- union struct的内存分配方式及其sizeof大小
- C++中struct/class的数据对齐与sizeof
- struct和 union用 sizeof 看字节对齐
- C++中常见数据类型的sizeof值,以及计算struct和union的详细方法
- 自然对齐:sizeof struct, union
- struct和 union用 sizeof 看字节对齐,以及__declspec( align( # ) ) 和 #pragma pack()的使用方式
- c++struct sizeof大小对齐方式
- union和struct对齐大小问题
- sizeof union struct 内存对齐
- 【C++ Primer】 神秘的 sizeof(union) 、sizeof(struct) 和内存对齐技术
- 【C++ Primer】 神秘的 sizeof(union) 、sizeof(struct) 和内存对齐技术
- sizeof union struct 内存对齐
- Windows下struct和union字节对齐设置以及大小的确定(一 简介和结构体大小的确定)
- 【C++ Primer】 神秘的 sizeof(union) 、sizeof(struct) 和内存对齐技术
- 【C++ Primer】 神秘的 sizeof(union) 、sizeof(struct) 和内存对齐技术
- 神秘的 sizeof(union) 、sizeof(struct) 和内存对齐技术
- union/struct 位对齐算大小
- union, struct , sizeof. 对齐
- (经典)struct和 union用 sizeof 看字节对齐,以及__declspec( align( # ) ) 和 #pragma pack()的使用方式