内存对齐的原则

1.结构体的第一个元素地址必须是0x…..0(是受内存对齐这个影响产生的结果)
2.结构体成员地址是通过对齐规则和自身大小共同影响的,规则如下:
如果设定对齐方式为n个字节对齐,而某结构体成员大小为m,那么该结构体成员的地址必须为min(n,m)的整数倍,比如double在64位平台是8字节,指定对齐方式为1个字节对齐,则地址随意,若为2个字节对齐,则地址只能是0 2 4 8
3.通过以上方式,即可算出结构体所有成员(附带填充所占字节)的大小q,而结构体的大小必须为大于q的min(n,maximum)的最小整数倍(n语义同上,maxiumum为最大的成员字节数)

下面我们来通过实例来搞懂上面的规则

#include 

using std::cout;
using std::endl;
#pragma pack(1)
struct Test {
    char c;     // 1 byte
    double d;   // 8 byte
    int i;      // 4 byte
    short s;    // 2 byte
    float f;    // 4 byte
};
#pragma pack()

#pragma pack(2)
struct Test2 {
    char c;     // 1 byte
    double d;   // 8 byte
    int i;      // 4 byte
    short s;    // 2 byte
    float f;    // 4 byte
};
#pragma pack()

#pragma pack(8)
struct Test8 {
    char c;     // 1 byte
    double d;   // 8 byte
    int i;      // 4 byte
    short s;    // 2 byte
    float f;    // 4 byte
};
#pragma pack()
int main() {
    //Test结构体以1字节对齐,总大小为1的倍数 因此为所有成员大小之和即可无需填充
    Test test;

    printf("Test 以%ld byte 对齐\n",alignof(Test));
    printf("Test结构体大小: %ld\n",sizeof(Test));
    printf("Test.c address:  %p\n",&test.c);
    printf("Test.d address:  %p\n",&test.d);
    printf("Test.i address:  %p\n",&test.i);
    printf("Test.s address:  %p\n",&test.s);
    printf("Test.f address:  %p\n",&test.f);
    //Test结构体以2字节对齐,总大小必须为2的倍数,成员与成员填充之和为(可以通过地址相减加尾元素大小) 20为2的倍数无需填充
    Test2 test2;    
    printf("Test2 以%ld byte 对齐\n",alignof(Test2));
    printf("Test2结构体大小: %ld\n",sizeof(Test2));
    printf("Test2.c address:  %p\n",&test2.c);
    printf("Test2.d address:  %p\n",&test2.d);
    printf("Test2.i address:  %p\n",&test2.i);
    printf("Test2.s address:  %p\n",&test2.s);
    printf("Test2.f address:  %p\n",&test2.f);
    //Test结构体以8字节对齐,总大小必须为8的倍数,成员与成员填充之和为 27不为8的倍数,继续填充直到32
    Test8 test8;    
    printf("Test8 以%ld byte 对齐\n",alignof(Test8));
    printf("Test8结构体大小: %ld\n",sizeof(Test8));
    printf("Test8.c address:  %p\n",&test8.c);
    printf("Test8.d address:  %p\n",&test8.d);
    printf("Test8.i address:  %p\n",&test8.i);
    printf("Test8.s address:  %p\n",&test8.s);
    printf("Test8.f address:  %p\n",&test8.f);
    return 0;
}

你可能感兴趣的:(程序员的自我修养)