【问题标题】:Why does union & inner struct add padding?为什么联合和内部结构添加填充?
【发布时间】:2018-02-10 13:30:21
【问题描述】:

在 amd64 上,以下结构的大小为 16 个字节:

typedef struct _my_struct {
    void *a;
    UINT32 b;
    UINT16 c;
    UINT8 d;
    UINT8 e;
} my_struct;

但是当我把前三个变量放在一个联合中时,大小变成了 24。为什么?

typedef struct _my_struct {
    union {
        struct {
            void *a;
            UINT32 b;
            UINT16 c;
        } my_inner;
        struct {
            void **f;
        } my_inner2;
    }
    UINT8 d;
    UINT8 e;
} my_struct;

【问题讨论】:

  • 联合无关。这是导致填充的内部结构。
  • 这是我的问题的一个过于简单的例子。当然,在我的真实结构中,联合中有很多东西。
  • 你为什么要介绍 1 个东西的 union

标签: c padding unions


【解决方案1】:

您正在创建一个新的结构类型 (my_inner)。编译器向该结构添加填充,使其大小变为 16 字节(对于 amd64)。然后它向外部结构类型 (my_struct) 添加填充,使其大小增长到 24 字节。

【讨论】:

  • 打包内部结构会有性能问题吗?
  • 我不这么认为,因为所有成员仍然会根据他们的类型自然对齐。但与往常一样,如果你想确定的话,你应该进行分析。
  • @NickBanks 编译器在结构的末尾添加了填充,因此它与数组中的相同结构兼容。
  • @NickBanks 因为它指定结构将在任何地方出现相同的布局。否则你会在复制东西时遇到麻烦。这种疯狂是有办法的!
  • @Persixty 是的,在这种情况下已经没有内部填充,因为即使没有填充,所有成员都是对齐的,唯一的填充在末尾。所以打包结构可能不会影响性能
【解决方案2】:

仅供参考,不增加整体尺寸的最简单解决方案是执行以下操作:

typedef struct _my_struct {
    union {
        struct {
            void *a;
            UINT32 b;
            UINT16 c;
        } my_inner;
        struct {
            void **f;
        } my_inner2;
        struct {
            UCHAR __PADDING[sizeof(void*) + sizeof(UINT32) + sizeof(UINT16)];
            UINT8 d;
            UINT8 e;
        };
    }
} my_struct;

它不漂亮,但它实现了我想要的,无需打包任何东西。

【讨论】:

    猜你喜欢
    • 2018-05-08
    • 2023-03-29
    • 1970-01-01
    • 2019-07-09
    • 2011-10-26
    • 2021-10-15
    • 1970-01-01
    • 2022-01-16
    • 1970-01-01
    相关资源
    最近更新 更多