c/c++ 结构体字节对齐规则

1.成员的偏移量offset要调整到成员自身对齐参数的整数倍。

struct C {
    char a;    // [a1] offset=0, char数据默认的对齐参数为1,不需要调整
    short b;   // [b1][b2]  offset=1, short数据默认的对齐参数为2,因此offset需要调整为2的整数倍,即offset调为2, 在前面数成员a末尾填充一个字节。
    int c;     // [c1][c2][c3][c4] offset=4, int数据默认的对齐参数为4,不需要调整。
    double d;  // [d1][d2][d3][d4][d5][d6][d7][d8]   offset=8, double数据对齐参数为8,不需要调整
    char e;    // [e1]   offset=16, char数据默认的对齐参数为1,不需要调整
    float f;   // [f1][f2][f3][f4]   offset=17, float数据默认的对齐参数为4,offset调到20,所以在前面的数据成员e末尾填充3字节
};

//** 总计填充了4个字节,算得struct C的大小为20+4=24字节,恰好为最大对齐参数8的整数倍,不必在最后填充

2.嵌套结构体成员也遵循第一条规则。

struct D {
    char a;
    double b;
};//struct D 默认对齐参数是8字节
struct B {
    char a;
    struct D d;//offset从1调整为8
};// 因此 struct B的大小为24.

#pragma pack(1)

struct D {
    char a;
    double b;
};//struct D 对齐参数设为1字节

#pragma pack()
struct B {
    char a;
    struct D d;//offset=1,不调整
};// 因此 struct B的大小为10.

3.结构体最终size大小要调整为最大对齐参数的整数倍,需要在最后一个成员后面填充补齐。

struct CC {
    char a;
    short b;
    int c;
    double d;//所有成员中, d的对齐参数是最大的,为8
    char e;
    float f;
    char g;//前面所有成员包括填充的字节数加起来共有24字节,加数据成员g变成25字节,调整到8的倍数32
};//因此struct CC的大小为32.

4.#pragma pack可以人为指定成员数据的对齐参数n(n= 2^{k} \left \{ k=0,1,2,... \right \},n必须为2的指数函数,否则设置无效)。如果n大于成员默认的对齐参数,则计算该成员偏移量时忽略该设置。n为有效数据的情况下,结构体最终size要调整为n的整数倍,这一点覆盖了规则三。

#pragma pack(2)

struct CCC {
    char a;
    short b;
    int c;
    double d;
    char e;
    float f;
    char g;//前面所有成员包括填充的字节数加起来共22字节,再加数据成员g,变成23字节,调整到2的倍数24
};//因此struct CCC的大小为24.

#pragma pack()

// 如果pack(4) 则struct CCC 大小为28;如果pack(8) 则struct CCC大小为32。可以想想它们分别是在哪些地方进行了补齐操作。

你可能感兴趣的:(c++,c语言)