C++ 内存对齐

struct Align{
    char a[9];
    int b = 0x44;
    char c = 0x55;
    double d;
    char e = 0x66;
};

int main()
{
    std::cout << alignof(Align) << std::endl;
    std::cout << offsetof(Align, b) << std::endl;
    std::cout << sizeof(Align) << std::endl;
    alignas(16) Align obj;
    std::cout << alignof(obj) << std::endl;
    std::cout << sizeof(obj);
    return 0;
}

输出如下:

8
12
40
16
40


变量对应的内存除位置(即地址属性),长度属性,还有对齐属性。对于变量的内存对齐属性,通过 alignof 可以获取。默认情况下,变量的对齐属性与变量的长度属性相同。自定义的数据类型 Align ,b 的对齐属性为4,所以实际b在对象中的偏移量为12(9 之后4的最小倍数,可通过 offsetof(Align, b) 来获取)。

c 占一个字节,而d的对齐属性为8,故d的偏移量为 12 + 4 + 1 后8的最小倍数,即24,所以e的偏移量为24 + 8,而自定义类型的总的存储大小必须为最大对齐成员的整数倍,这样才能保证在数组当中,数组中的所有成员内部也是满足对齐的,所以e后边需要填充7个字节,使总的字节数为33之后8的最小倍数40.

C++11 之后通过alignas 来改变对齐属性,obj 的默认对齐属性为8,通过alignas 改变成16。注意这样的改变只是改变 obj 这一个对象。而要定义一种对齐的类型,可使用using 来达到。using Align_16 alignas(16) = Align;  (写法稍稍奇怪),之后便可以用类型 Align_16 定义更多的变量。

struct Align{
    char a[9];
    int b = 0x44;
    alignas(16) char c = 0x55;   //添加对齐方式限定
    double d;
    char e = 0x66;
};

int main()
{
    std::cout << alignof(Align) << std::endl;
    std::cout << offsetof(Align, b) << std::endl;
    std::cout << sizeof(Align) << std::endl;
    alignas(16) Align obj;
    std::cout << alignof(obj) << std::endl;
    std::cout << sizeof(obj);
    return 0;
}
输出如下:

16
12
48
16
48

添加了对齐方式之后,由于c原来的对齐属性是16,所以不变,d,e 的也跟着不变。只是,最大的对齐属性为16,所以在 e 后边需要填充15 个字节,使总的长度为48,达到16的倍数。

你可能感兴趣的:(C++,LEARNING,DIARY)