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 A
与struct 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。