C结构体对齐问题
前提条件:确认所有基本数据类型分别占用多少个字节。(这个不完全跟平台一致,不要简单地说8位机,16位机, 32位机, 64机,它还跟编译器本身密切相关)
这里就拿32位平台下,并且sizeof(char)=1, sizeof(short)=2, sizeof(int)=4 sizeof(long)=8的情况来说明。(听到32位就理所当然地说是按4字节对齐也是致命的。 )
几个注意事项:
1. 当前结构体成员本身需要几个字节来储存。(以上都有说明,看成员类型就知道了)
2. 下一个结构成员所需要的空间。(如果下一个成员占用字节较大,当前和往后都按大的字节数来对齐)
3. 当前结构体成员当中,占用最多的成员是多少个字节。(这里的“当前结构体”是指从第一个成员到正在分析的那个成员为止的结构体)
4. 正在分析的成员按新的对齐来处理后,需要填充的字节是否能够存下一个成员。如果可以,下一个成员有定义和无定义都不会对总占用
字节数产生影响。
(在分析结构所占字节数时,请按顺序进行)
下面举个例子
typedef struct
{
char a;
short b;
int c;
long d;
char e;
}test_t;
请问以上结构体在当前约束条件下,占用多少字节的内存空间?
分析:
从第一个成员开始:
char a;(1) 它占用一个字节, (2)它的下一个成员 short b; 需要占用2个字节 (3) 到short b;为止占用字节最多的是2字节的short b; 好,到此为止,结构会按当前占用字节数最大的成员所占用的字节数来对齐,也就是按2字节对齐,所以char a; short b;一共要占用4个字节 。
现在开始分析int c;
毫无疑问到此为止占8个字节。
同理, long d; 加入后占16字节, 但到此为止,结构体中占字节最多的是8字节的long, 所以后面增加的成员只要是在8字节以内,都得占
8字节 ,哪怕char e;只占了一个字节,因为在此之后,要按8字节来对齐了。
所以sizeof(test_t) = 2+2+4+8+8=24字节。
下面来一题,巩固一下:
typedef struct
{
char a; //2 (本来占1字,因为后面的b要2字节对齐,所以要填充一个字节)
short b; //2 (当前占四字节,后面的c也占四字节,刚好对齐,所以不用填充,就占2字节)
int c; //4 (后面的d, 只占一个字节, 所以c不用填充, 但往后要按4字节对齐了)
char d //8 (如果没有后面的long e, 它是按4字节对齐至少要占用4字节,但后面来个long e, 需要填充7字节,所以d 要占用8个字节)
long e; //8
char f[9];//16
} test_t;
sizeof(test_t) = 2+2+4+8+8+16=40;
另外,如果用了#pragam pack(n) //n为 >=0 且为2的较小次方的整数, 或者不写
那么对齐方式是按设定的来。
比如
#pragma pack(1)
typedef struct
{
char a;
short b;
int c;
char d;
long e;
char f[9];
} test_t;
#pragma pack()
它按1字节对齐,只占25字节。
如果上述结构体,指定pack(2)那么它就只占28字节。
总结起来就是:
1. 当前成员占多少字节
2. 下个成员占多少字节
3. 当前和往后按多少字节对齐
4. 新的对齐方式下,当前成员填充的字节数够不够容得下下一个成员。
。。。。
1. 当前成员占多少字节
2. 下个成员占多少字节
3. 当前和往后按多少字节对齐
4. 新的对齐方式下,当前成员填充的字节数够不够容得下下一个成员。。。。。
1. 当前成员占多少字节
2. 下个成员占多少字节
3. 当前和往后按多少字节对齐
4. 新的对齐方式下,当前成员填充的字节数够不够容得下下一个成员。这是一个递归的过程,用好它去分析每一个成员就行了。
希望从此不要再询问结构体字节对齐的问题了。纯手工打的,网上找不到的。