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.  新的对齐方式下,当前成员填充的字节数够不够容得下下一个成员。这是一个递归的过程,用好它去分析每一个成员就行了。

希望从此不要再询问结构体字节对齐的问题了。纯手工打的,网上找不到的。

You may also like...

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据