打包结构大小为 40,即使成员大小增加到 36

问题描述 投票:0回答:1

struct

K
已打包,其类成员大小的总和为 36。每个成员都有一个
static_assert
检查这一点。

但是,

K
本身的大小是40,而不是36。K不是多态的等等。

为什么

K
不是36号?

使用 Clang 16。我不知道有一种简单的方法来可视化结构,或者我会的。如果有人能推荐一种方法那就太好了。

template<class S>
struct P
{};

struct D : public P<D>
{
    uint64_t x_;
};

enum class E : uint8_t
{};

struct K
{
    D a_;          
    D b_;          
    uint64_t c_;   
    uint64_t d_;   
    uint16_t e_;   
    E f_;          
    E g_;          

    static_assert(sizeof(a_) == 8); // Passes
    static_assert(sizeof(b_) == 8); // Passes
    static_assert(sizeof(c_) == 8); // Passes
    static_assert(sizeof(d_) == 8); // Passes
    static_assert(sizeof(e_) == 2); // Passes
    static_assert(sizeof(f_) == 1); // Passes
    static_assert(sizeof(g_) == 1); // Passes

}__attribute__((packed));

static_assert(sizeof(K) == 36); // Fails, is 40 instead of 36

int main()
{
    K f;
}
c++ attributes clang structlayout
1个回答
0
投票

启用 clang 警告后,问题变得显而易见:

<source>:17:7: warning: not packing field 'a_' as it is non-POD
               for the purposes of layout [-Wpacked-non-pod]
   17 |     D a_;          
      |       ^
<source>:18:7: warning: not packing field 'b_' as it is non-POD
               for the purposes of layout [-Wpacked-non-pod]
   18 |     D b_;          
      |       ^

GCC 和 clang 似乎都没有记录此行为(请参阅 GCC

packed
属性clang
packed
属性
),但看起来使用继承(来自
P<D>
)会禁用
packed
的效果成员。 在这种情况下,没有任何内在原因导致
D
无法打包,这只是一个普遍的禁令。

如果有任何成员未包装,为了确保所有成员正确对齐,

struct
需要额外的填充。
K
的对齐是
8
,证明如下:

static_assert(alignof(K) == 8); // passes; alignment is normally 1 for packed types

由于

K
对齐到 8 字节,并且其成员的组合大小为 36,因此必须在末尾添加 4 个填充字节,以将
K
正确对齐到 8 字节(通过将其大小增加到 40)。

© www.soinside.com 2019 - 2024. All rights reserved.