C - alignas没有给出预期的结果

Eri*_*k W 1 c

Alignas在C11没有像我期待的那样工作.这是我的代码:

#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));
}
Run Code Online (Sandbox Code Playgroud)

输出:

2, 2
4, 4
4, 4
4, 8
4, 8
4, 8
Run Code Online (Sandbox Code Playgroud)

我预计所有这些结构的大小都是一样的.为什么struct A尺寸不一样struct B?我误解了怎么alignas运作?

mel*_*ene 5

假设int16_t需要2字节对齐并且int32_t需要4字节对齐.

struct A
{
    alignas(int32_t) int16_t a;
    int16_t b;
};
Run Code Online (Sandbox Code Playgroud)

这个的自然布局是2个字节a,2个字节b,以及整个结构的2字节对齐.

但是alignas(int32_t)引入了额外的约束:a必须在4字节边界上对齐.这会强制整个结构在4字节边界上对齐.但是大小a仍然只是2个字节,因此b可以在(4n + 2)字节边界上立即放置,没有填充.在2个字节后,b我们在4n + 4上,即再次在4字节边界上.这意味着我们之后不需要填充b:我们可以立即启动结构的另一个实例.

总而言之,我们有一个没有填充的结构(sizeof (struct A)是其成员大小的总和,4)和第一个成员的对齐,4.

struct B
{
    int16_t a;
    alignas(int32_t) int16_t b;
};
Run Code Online (Sandbox Code Playgroud)

这种情况不同:a它本身只强制2字节对齐.但是现在b必须在4字节边界上对齐,因此整个结构必须在4字节边界上对齐,然后插入2字节的填充a.到目前为止,我们有2个字节a,2个字节的填充,2个字节b,它们将我们置于(4n + 6)(即4n + 2)字节边界.我们需要达到我们开始的状态,然后插入另外2个字节的填充b以确保我们以4字节边界结束.

总而言之,我们最终得到2 + 2字节的填充和2 + 2字节的内容,大小为8.