未打包的结构体是否会自动打包到已打包的结构体中?

8

未打包的结构体在GCC中自动打包到打包的结构体中吗?

换句话说,__packed__属性是否会自动传播到嵌套结构体中?

也就是说:

struct unpackedStruct{
    int16_t field1;
    int32_t field2;
    // etc...
}

struct packedStruct{
    int16_t field1;
    struct unpackedStruct struct1; // <-- Is this struct packed?
    // etc...
} __attribute__((__packed__));

3
最好不要这样,否则将该成员传递给任何其他期望普通的 unpackedStruct 的代码都将失败。无论如何,您可以进行测试。 - Nate Eldredge
@NateEldredge 此外,直接从一个变量赋值给另一个变量是无效的。 - Andrew Henle
使用编译器检查这应该很容易。 - eerorika
3个回答

11
不,内部结构没有被打包。在这个Godbolt示例中,我们可以看到struct foo没有被打包在有packed属性的struct bar内部;创建的struct bar对象包含三个字节的填充(在其struct foo成员内可见,位于struct foo成员和之间。 GCC 10.2的当前文档明确表示,打包结构的成员的内部布局没有被打包(因为外部结构有该属性;当然,它可能由于自身定义而被打包)。
(在旧文档中,它说将packed应用于结构等同于将其应用于其成员,它指的是应用于成员的“变量”的效果,描述在变量属性的文档中。当将packed应用于结构成员时,它会导致该成员的对齐要求为一个字节。也就是说,它消除了先前成员和该成员之间的填充,因为不需要填充使其对齐。它不会改变成员本身的表示。如果该成员是未打包的结构,则它在内部仍然是未打包的结构。)

2
实际上,这并不会发生:请参见https://godbolt.org/z/4YMaz8。 请注意,在unpackedStruct成员的两个成员之间有.zero 2字节的填充。
这种情况在手册中明确提到,并且几乎与您的示例相同:

在下面的示例中,struct my_packed_struct的成员紧密地打包在一起,但是其s成员的内部布局没有打包 - 要做到这一点,struct my_unpacked_struct也需要被打包。

struct my_unpacked_struct
 {
    char c;
    int i;
 };

struct __attribute__ ((__packed__)) my_packed_struct
  {
     char c;
     int  i;
     struct my_unpacked_struct s;
  };

基本思想是给定类型的每个对象都应该具有相同的布局,以便对该类型进行操作的代码将在该类型的每个对象上运行。因此,packed必须应用于一个类型,而不能有一些该类型的对象被打包,而另一些没有。

我认为barfoo代码必须被打破,因为&p.struct1可能不会像struct my_unpacked_struct一样对齐。Clang会产生“error: taking address of packed member 's' of class or structure 'my_packed_struct' may result in an unaligned pointer value [-Werror,-Waddress-of-packed-member]”的错误,而GCC 10.2则保持沉默。 - Eric Postpischil
好的,假设它会更糟——在没有严格对齐要求的平台上,它很可能会工作。或者你可以想象将__attribute__((aligned(1)))应用于struct unpackedStruct - Nate Eldredge
@EricPostpischil:但我无论如何都会将其删除。 - Nate Eldredge
我会保留它,但是单独提到对齐问题。如果 struct foo 成员真正被打包,它根本不能用作 struct foo。但由于它没有被打包,只是错位对齐,实际上有两种类型,即 struct foostruct foo __attribute__((__aligned__(1)))。你可以将一个 memcpy 到另一个。 - Eric Postpischil

0

不会 - 打包不是递归的,所以每个成员本身都需要被打包。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接