struct 是一种复合数据类型,其构成元素既可以是基本数据类型(如 int 、 long 、 float 等)的变量,也可以是一些复合数据类型(如 array 、 struct 、 union 等)的数据单元。对于结构体,编译器会自动进行成员变量的对齐,以提高运算效率。缺省情况下,编译器为结构体的每个成员按其自然对界( natural alignment )条件分配空间。各个成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构的地址相同。
一、自然对界 (natural alignment) 即默认对齐方式,是指按结构体的成员中基本类型size 最大的成员对齐。(注意:记住是基本类型 !)
例如:有如下结构体
struct PRG
5 {
6 int c;
7 union
8 {
9 char st[6];
10 int i;
11 long int j;
12 }test;
13 char b;
14 };
按照自然对界方式,应以成员 j 类型(long int)大小对齐,即8字节;则sizeof(struct PRG)为 24;在内存中结构图如下:
|————————|————————|————————|
|int c | 填充 | union test |b| 填充 |
以下再给几个例子,让读者好好体会上面的文字的意思,特别是红色标记的字眼。
struct testa
17 {
18 char a;
19 char b;
20 char c;
21 }ta; sizeof(ta) 为 3
struct testb
17 {
18 char a;
19 char b[3];
20 char c;
21 }tb; sizeof(tb) 为 5
struct testc
17 {
18 char a;
19 short b;
20 char c;
21 }tc; sizeof(tc) 为 6
struct testd
17 {
18 char a;
19 char c;
20 short b;
21 }td; sizeof(tc) 为 4 (因为a与c合在一起刚好对齐)
struct teste
17 {
18 char a;
19 int b;
20 char c;
21 }te; sizeof(tc) 为 12
struct testc
17 {
18 char a;
19 char c;
20 int b;
21 }tc; sizeof(tc) 为 8
二、改变对齐的方式。
在缺省情况下,C编译器为每一个变量或是数据单元按其自然对界条件分配空间。
一般地,可以通过下面的方法来改变缺省的对界条件:
·使用伪指令#pragma pack(n),C编译器将按照n个字节对齐。
·使用伪指令#pragma pack(),取消自定义字节对齐方式。
注意:如果 #pragma pack (n) 中指定的 n 大于结构体中最大(指基本类型)成员的 size ,则其不起作用,结构体仍然按照 size 最大的成员进行对齐。
另外,还有如下的一种方式:
·__attribute__((aligned(n))),让所作用的结构成员对齐在n字节自然边界上。如果结构中有成员的长度大于n,则按照最大成员的长度来对齐。
·__attribute__((packed)),取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐.
注意:上述的n必须为2的某次方!
例:
#pragma pack(4)
struct PRG
5 {
6 int c;
7 union
8 {
9 char st[6];
10 int i;
11 long int j;
12 }test;
13 char b;
14 };
#pragma pack() 则sizeof(struct PRG)为 16
#pragma pack(1)
struct PRG
5 {
6 int c;
7 union
8 {
9 char st[6];
10 int i;
11 long int j;
12 }test;
13 char b;
14 };
#pragma pack() 则sizeof(struct PRG)为 13
#pragma pack(16)
struct PRG
5 {
6 int c;
7 union
8 {
9 char st[6];
10 int i;
11 long int j;
12 }test;
13 char b;
14 };
#pragma pack() 则sizeof(struct PRG)仍为 24
struct PRG
5 {
6 int c;
7 union
8 {
9 char st[6];
10 int i;
11 long int j;
12 }test;
13 char b;
14 }__attribute__((aligned(4))); 则sizeof(struct PRG)仍为 24
struct PRG
5 {
6 int c;
7 union
8 {
9 char st[6];
10 int i;
11 long int j;
12 }test;
13 char b;
14 }__attribute__((aligned(16))); 则sizeof(struct PRG)为 32