数据对齐 问题心得

最近在复习C语言,感觉自己以前对C的学习和认识简直是shit。今天看到有关结构体中成员存储分配的数据对齐问题,想和大家分享一下,也谈不上心得,就是想总结一下而已。 有关数据对齐有两种,一种为自然对齐,一种为强制对齐。1.先看自然对齐,有如下程序:

  #include <stdio.h>
    typedef struct
    {
        char c1;
        long l;
        char c2;
        double d;
    }a;
    
    typedef struct
    {
        char c1;
        char c2;
        long l;
        double d;
    }b;
    int main()
    {
        printf("%d,%d\n",sizeof(a),sizeof(b));
        return 0;
    }

打印结果为: 1 分析如下:两个结构体的成员变量完全相同,但是次序不同,数据对齐后结构体所占空间也不尽相同。结构体a在自然对齐后的状态如下: 2

c1为char类型占用一个字节,之后为了让l自然对齐,因此需要填充3个字节。l为long型,占用4个字节,c2为char型,为了让双精度的d对齐,需要在c2添加7个字节,之后d占用8个字节。所以结果为:1+3+4+1+7+8=24。按同样的规则易得结构体b所占空间为16。 关于自然对齐规则也可以总结为:各成员变量存放的地址相对于结构的起始地址的偏移量为sizeof(类型)或其整数倍。结构的总大小是其成员中最大类型的sizeof(该类型)整数倍。所以在定义结构体时最好把结构中的变量按照类型大小从小到大声明,以减少中间的填补空间。

2.关于强制对齐,使用#pragma pack(n) 设定对齐系数。

#pragma pack(4)
    typedef struct
    {
        char c1;
        long l;
        char c2;
        double d;
    }a;
    #pragma pack()

打印结果如下,a的大小变为了20 3 设n=8

#pragma pack(8)
    typedef struct
    {
        char c1;
        long l;
        char c2;
        double d;
    }a;
    #pragma pack()

a类型的大小和自然对齐的结果相同还是24 4

因为使用#pragma pack(n) 设定对齐系数分为两种情况:第一、如果n大于等于该成员所占用的字节数,那么偏移量必须满足默认的对齐方式,即自然对齐方式。第二、如果n小于该成员的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式。结构的总大小也有个约束条件,分下面两种情况:如果n大于所有成员变量类型所占用的字节数,那么结构的总大小必须为占用空间最大的变量占用的空间数的倍数; 否则必然为n的倍数。 那个某*,街拍刚巴呆~

【参考文献】「程序员求职成功路」

王小兵 /
Published under (CC) BY-NC-SA in categories C&C++  tagged with C语言