C11中的Alignas未按预期工作。这是我的代码:

#include <inttypes.h>
#include <stdalign.h>
#include <stdio.h>

struct A
{
    alignas(int32_t) int16_t a;
    int16_t b;
};

struct B
{
    int16_t a;
    alignas(int32_t) int16_t b;
};

struct C
{
    int16_t a;
    int32_t b;
};

struct D
{
    int32_t a;
    int16_t b;
};

int main(void)
{
    printf("%zu, %zu\n", alignof(int16_t), sizeof(int16_t));
    printf("%zu, %zu\n", alignof(int32_t), sizeof(int32_t));
    printf("%zu, %zu\n", alignof(struct A), sizeof(struct A));
    printf("%zu, %zu\n", alignof(struct B), sizeof(struct B));
    printf("%zu, %zu\n", alignof(struct C), sizeof(struct C));
    printf("%zu, %zu\n", alignof(struct D), sizeof(struct D));
}

输出:
2, 2
4, 4
4, 4
4, 8
4, 8
4, 8

我希望所有这些建筑的大小都一样。为什么struct Astruct B大小不同我是不是误解了alignas的工作原理?

最佳答案

假设int16_t需要2字节对齐,int32_t需要4字节对齐。

struct A
{
    alignas(int32_t) int16_t a;
    int16_t b;
};

它的自然布局是a为2字节,b为2字节,整个结构为2字节对齐。
但是alignas(int32_t)引入了额外的约束:a必须在4字节边界上对齐这将强制整个结构在4字节边界上对齐。但是a的大小仍然只有2个字节,因此b可以在之后立即放置在(4n+2)字节的边界上,无需填充对于b的2字节后,我们在4n+4上,即再次在4字节边界上这意味着b之后不需要填充:我们可以立即启动该结构的另一个实例。
总之,我们有一个没有填充的结构(sizeof (struct A)是它的成员的大小之和,4)和它的第一个成员的对齐方式,4。
struct B
{
    int16_t a;
    alignas(int32_t) int16_t b;
};

这里的情况不同:a本身只强制2字节对齐但是现在b必须在4字节的边界上对齐,所以整个结构必须在4字节的边界上对齐,并且在a之后插入2字节的填充到目前为止,我们有2个字节用于a,2个字节填充,2个字节用于b,这使我们处于(4n+6)(即4n+2)字节边界我们需要达到我们开始的状态,所以在b之后再插入2字节的填充,以确保我们以4字节的边界结束。
总之,我们最终得到了2+2字节的填充和2+2字节的内容,使大小为8。

10-07 15:15