字段的 __attribute__((packed)) 如何影响包含该字段的结构?

Posted

技术标签:

【中文标题】字段的 __attribute__((packed)) 如何影响包含该字段的结构?【英文标题】:How does __attribute__((packed)) for a field affect struct which contains this field? 【发布时间】:2019-01-02 17:44:08 【问题描述】:

如果我的结构中有一个已打包的字段,为什么我的整个结构都被打包了?

例子:

#include <stdio.h>

struct foo 
  int a;
 __attribute__((packed));

struct bar 
  char b;
  struct foo bla;
  char a;
;

int main() 
  printf("%ld\n", sizeof(struct bar));
  return 0;

https://ideone.com/bjoZHB

bar struct 的 Sizeof 是 6,但应该是 12,因为它应该是对齐的。

【问题讨论】:

【参考方案1】:

似乎是因为__attribute__((packed)) 意味着对结构使用最小内存,这也意味着当它在另一个结构中时它可以忽略侧板成员的对齐。检查以下结构:

struct bar 
  char b;
  __attribute__((packed)) int bla;
  char a;
;

当您检查此结构的大小时,它将是 6。发生这种情况是因为它忽略了 2 个侧面成员的成员对齐(@9​​87654324@ 和 b 此处)。但是这个结构:

struct bar 
  char b;
  __attribute__((packed)) int bla;
  char a;
  int c;
;

大小为 12,因为它在 4 字节边界上对齐 c。在您的情况下,如果您同时使用 aligned 属性,它会按您的预期工作:

struct bar 
  char b;
  __attribute__((aligned (4), packed)) int bla;
  char a;
;

这个结构大小是12。

更新:

我只在 attributes 的 GCCaligned 部分找到了这个。我认为这与我在这里提到的有关:

aligned属性只能增加对齐;但是你可以 通过指定 packed 来减少它

.请记住,如果您想保持子结构打包但主结构对齐,则需要在 2 个不同的声明中使用 2 个属性。例如以下结构的大小为 12:

struct foo 
  char b;
  int a;
 __attribute__((packed));

struct bar 
  char b;
  __attribute__((aligned(4))) struct foo bla;
  char a;
;

但是如果你在foo 的声明中使用aligned() 作为__attribute__((aligned (4), packed)),大小将是16。这是因为foo 也对齐了,在打包的情况下它不会有用。

【讨论】:

我在哪里可以读到“意味着当它在另一个结构中时它可以忽略对齐”我在 gcc 文档或任何地方都没有找到它。 :( @SukhanovNiсkolay 它在句子的开头也有一个“似乎”。但我在 gcc 手册中找到了 1 句话,我将其添加到回复中。 是的,我看到了同样的引用,那么它似乎是 ISO C 的要求。 :) 更新:抱歉,引用错误,我看到了:“ISO C 标准至少是结构所有成员对齐的最低公倍数的完美倍数”

以上是关于字段的 __attribute__((packed)) 如何影响包含该字段的结构?的主要内容,如果未能解决你的问题,请参考以下文章

GCC 的 __attribute__((__packed__)) 是不是保留原始顺序?

__attribute__((packed))作用

如果我将字节数组转换为 __attribute__((packed, aligned(2))) 结构会发生啥?

高级C__attribute__((aligned(n))) 与 #pragma(pack(n))的区别

高级C__attribute__((aligned(n))) 与 #pragma(pack(n))的区别

“#pragma pack”和“__attribute __((aligned))”之间的区别是什么?