字段的__attribute __((packed))如何影响包含此字段的结构?

时间:2019-01-02 17:44:08

标签: c gcc

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

示例:

#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结构的sizeof为6,但应为12,因为它应该对齐。

1 个答案:

答案 0 :(得分:6)

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

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

当您检查此结构的大小时,它将为6。之所以发生这种情况,是因为它忽略了2个侧成员的成员对齐方式(此处为ab)。但是这个结构:

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。

更新

我仅在attributesGCC aligned 部分中找到了这一点。我认为这与我在这里提到的内容有关:

  

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

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

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

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

但是如果在aligned()的声明中将foo用作__attribute__((aligned (4), packed)),则大小将为16。这是因为foo也对齐了,因此将无用包装时。