[转]结构体字节对齐规则
1 //先介绍三个概念:自身对齐值、指定对齐值、有效对齐值。 2 3 //自身对齐值:数据类型本身的对齐值,例如char类型的自身对齐值是1,short类型是2; 4 //指定对齐值:编译器或程序员指定的对齐值,32位单片机的指定对齐值默认是4; 5 //有效对齐值:自身对齐值和指定对齐值中较小的那个。 6 7 //对齐有两个规则: 8 9 //1、不但结构体的成员有有效对齐值,结构体本身也有对齐值,这主要是考虑结构体的数组,对于结构体或者类,要将其补齐为其有效对齐值的整数倍。 10 // 结构体的有效对齐值是 [其最大数据成员的自身对齐值] 和 [编译器或程序员指定的对齐值] 中较小的那个; 11 //2、存放成员的起始地址必须是该成员有效对齐值的整数倍。 12 13 // 64 位系统 指定对齐值默认是8; 14 // 编译器或程序员指定的对齐值,通过下面的命令,指定为 4 byte对齐 15 #pragma pack (4) 16 17 // 简单类型的结构体对齐 18 typedef struct { 19 char a; // 1 byte 3 byte reserved(成员b起始对齐) 20 float b; // 4 byte 21 char c; // 1 byte 3 byte reserved(结构体本身对齐) 22 }StructA; // 12 byte 23 24 typedef struct { 25 char a; // 1 byte 3 byte reserved(成员b起始对齐) 26 double b; // 8 byte 27 char c; // 1 byte 3 byte reserved(结构体本身对齐) 28 }StructAA; // 16 29 30 typedef struct { 31 double a; // 8 byte 32 char b; // 1 byte 33 char c; // 1 byte 2 byte reserved(结构体本身对齐) 34 }StructAAA; // 12 35 36 typedef struct { 37 char a; // 1 byte 38 char b; // 1 byte 39 char c; // 1 byte 40 }StructAAAA; // 3 41 42 typedef struct { 43 short a; // 2 byte 44 char b; // 1 byte 1 byte reserved(结构体本身对齐) 45 }StructAAAAA; // 4 46 47 // 带有数组的结构体对齐 48 // 数组本编译器理解为多个基本类型的连续,并没有把他当做一个整体进行对齐 49 typedef struct { 50 char a; // 1 byte 3 byte reserved(成员b起始对齐) 51 float b[3]; // 12 byte 52 char c; // 1 byte 3 byte reserved(结构体本身对齐) 53 }StructB; // 20 byte 54 55 typedef struct { 56 char a; // 1 byte 57 char b[3]; // 3 byte 58 char c; // 1 byte 59 }StructBB; // 5 byte 60 61 typedef struct { 62 char a; // 1 byte 1 byte reserved(成员b起始对齐) 63 short b[3]; // 6 byte 64 char c; // 1 byte 1 byte reserved (结构体本身对齐) 65 }StructBBB; // 10 byte 66 67 // 结构体嵌套对齐对齐 68 // 嵌套的结构体是按结构体整体(可以认为是新的数据类型)进行对齐, 69 // 结构体变量的自身对齐值是 [其最大数据成员的自身对齐值] 和 [编译器或程序员指定的对齐值] 中较小的那个; 70 71 typedef struct { 72 char a[3]; // 3 byte 73 }StructC1; // 3 byte 74 75 typedef struct { 76 short a[3]; // 6 byte 77 }StructC2; // 6 byte 78 79 typedef struct { 80 double a; // 8 byte 81 char b; // 1 byte 3 byte reserved (结构体本身对齐) 82 }StructC3; // 12 byte 83 84 typedef struct { 85 short a; // 2 byte 86 char b; // 1 byte 1 byte reserved (结构体本身对齐) 87 }StructC4; // 4 byte 88 89 typedef struct { 90 char a; // 1 byte 3 byte reserved(成员b起始对齐) 91 StructA b; // 12 byte [大小是12,指定对齐值4,以指定对齐为有效对齐] 92 char c; // 1 byte 3 byte reserved(结构体本身对齐) 93 }StructD; // 20 byte 94 95 typedef struct { 96 char a; // 1 byte 97 StructC1 b; // 3 byte 98 char c; // 1 byte 99 }StructDD; // 5 byte 100 101 typedef struct { 102 char a; // 1 byte 1 byte reserved(成员b起始对齐) 103 StructC2 b; // 6 byte 104 char c; // 1 byte 1 byte reserved(成员b起始对齐) 105 }StructDDD; // 10 byte 106 //--------特殊的例子----------// 107 typedef struct { 108 StructC3 a; // 12 byte 109 char b; // 1 byte 3 byte reserved(成员b起始对齐) 110 }StructDDDD; // 16 byte 111 //--------特殊的例子----------// 112 typedef struct { 113 char a; // 1 byte 1 byte reserved(成员b起始对齐) 114 StructC4 b; // 4 byte 115 char c; // 1 byte 1 byte reserved(成员b起始对齐) 116 }StructDDDDD; // 6 byte
先介绍三个概念:自身对齐值、指定对齐值、有效对齐值。
自身对齐值:数据类型本身的对齐值,例如char类型的自身对齐值是1,short类型是2;
指定对齐值:编译器或程序员指定的对齐值,32位单片机的指定对齐值默认是4;
有效对齐值:自身对齐值和指定对齐值中较小的那个。
对齐有两个规则:
1、不但结构体的成员有有效对齐值,结构体本身也有对齐值,这主要是考虑结构体的数组,对于结构体或者类,要将其补齐为其有效对齐值的整数倍。结构体的有效对齐值是其最大数据成员的自身对齐值;
2、存放成员的起始地址必须是该成员有效对齐值的整数倍。
举四个例子

假如结构体起始地址是0x0000,
成员a的自身对齐值1,指定对齐值4,所以有效对齐值是1,地址0x0000是1的整数倍,故a存放起始地址是0x0000,占一个字节;
成员b的自身对齐值1,指定对齐值4,所以有效对齐值是1,地址0x0001是1的整数倍,故b存放起始地址是0x0001,占一个字节;
成员c的自身对齐值1,指定对齐值4,所以有效对齐值是1,地址0x0002是1的整数倍,故c存放起始地址是0x0002,占一个字节;
成员d的自身对齐值1,指定对齐值4,所以有效对齐值是1,地址0x0003是1的整数倍,故d存放起始地址是0x0003,占一个字节;
此时结构体A的有效对齐值是其最大数据成员的自身对齐值,它的成员都是char类型,故结构体A的有效对齐值是1.
结构体A的存储结构如下,其中Y是根据规则1补齐的字节,x是规则2补齐的字节。
|
0x0000 |
0x00001 |
0x0002 |
0x0003 |
|
a |
b |
c |
d |
根据以上规则可以知道其他结构体的存储结构:
结构体B占6个字节
|
0x0000 |
0x00001 |
0x0002 |
0x0003 |
0x0004 |
0x0005 |
|
a |
x |
b |
b |
c |
d |
结构体C占12个字节
成员a的自身对齐值1,指定对齐值4,所以有效对齐值是1,地址0x0000是1的整数倍,故a存放起始地址是0x0000,占一个字节;
成员b的自身对齐值4,指定对齐值4,所以有效对齐值是4,地址0x0004是4的整数倍,故b存放起始地址是0x0004,占四个字节;
成员c的自身对齐值1,指定对齐值4,所以有效对齐值是1,地址0x0008是1的整数倍,故c存放起始地址是0x0008,占一个字节;
成员d的自身对齐值1,指定对齐值4,所以有效对齐值是1,地址0x0009是1的整数倍,故d存放起始地址是0x0009,占一个字节;
结构体C的成员占据10个字节,而结构体C的有效对齐值是其成员b的自身对齐值4,10不是4的倍数,故还需补齐两个字节,此时结构体C占据12个字节,是4的倍数
如下:
|
0x0000 |
0x00001 |
0x0002 |
0x0003 |
0x0004 |
0x0005 |
0x0006 |
0x0007 |
0x0008 |
0x0009 |
0x000A |
0x000B |
|
a |
x |
x |
x |
b |
b |
b |
b |
c |
d |
Y |
Y |
结构体D占16个字节
|
0x0000 |
0x00001 |
0x0002 |
0x0003 |
0x0004 |
0x0005 |
0x0006 |
0x0007 |
0x0008 |
0x0009 |
0x000A |
0x000B |
0x000C |
0x000D |
0x000E |
0x000F |
|
a |
x |
x |
x |
b |
b |
b |
b |
b |
b |
b |
b |
c |
d |
Y |
Y |
代码验证如下:


浙公网安备 33010602011771号