【问题标题】:padding at last member of c struct在 c 结构的最后一个成员处填充
【发布时间】:2011-11-05 18:16:58
【问题描述】:

我总是假设,正如他们在这里所说的 http://en.wikipedia.org/wiki/Data_structure_alignment,“重要的是要注意最后一个成员填充了所需的字节数,因此结构的总大小应该是最大对齐的倍数任何结构成员”

所以对于这样的结构,它的大小在 32 处理器上应该是 16

typedef struct
{
   double   s;  /* 8 bytes */
   char     c;  /* 7 bytes padding at the end of make the total size 8*2 */
} structa_t;  

所以我对尺寸是 12 而不是 16 感到非常惊讶!这是为什么 ?有人可以解释一下吗?

sizeof(double) = 8
sizeof(structa_t) = 12

顺便说一句,系统信息

$ uname -a
Linux 2.6.18-8.el5xen #1 SMP Thu Mar 15 21:02:53 EDT 2007 i686 i686 i386 GNU/Linux
$ gcc --version
gcc (GCC) 4.1.1 20070105 (Red Hat 4.1.1-52)

【问题讨论】:

  • 你一定是指你所说的位的字节
  • 也许只是double只需要在四字节边界上对齐?
  • 您错过了结束 */ 的评论。
  • 谢谢。我已经更正了这些错别字

标签: c struct padding memory-alignment


【解决方案1】:

这里的关键词是:

...结构的总大小应该是任何结构成员的最大对齐方式的倍数...

在您的系统上,double 的对齐方式是 4,而不是 8。

如果等待 C1x,可以使用_Alignof 运算符(类似于sizeof)。在您的系统上,

sizeof(double) == 8
_Alignof(double) == 4

您可以在 C89 中以更原始的方式测试对齐方式,

#include <stdlib.h>
struct char_double { char x; double y; };
#define DOUBLE_ALIGNMENT offsetof(struct char_double, y)

或者用宏,

#define alignof(x) offsetof(struct { char a; x b; }, b)

【讨论】:

  • 如果等不及C1x,可以试试#define alignof(type) offsetof(struct { char c; type t; }, t),通常会得到很好的答案。我不能 100% 确定它可以保证工作,但似乎可以。
  • 谢谢。我进一步检查了那个 wiki,就像你说的那样,它确实说“双(8 字节)在 Windows 上将是 8 字节对齐,在 Linux 上是 4 字节对齐”。
  • @Chris Lutz:我犹豫是否建议该选项,因为我怀疑某些实现不支持它,但我意识到这是一个错误。
  • @Dietrich - 大约一个月前,我曾有过一段时间“等等,在offsetof 中使用内联定义的struct 类型总是可移植的吗?”并停止使用它,但我不记得是什么让我这么想了,我想不出任何原因。
  • @Chris Lutz:是什么让我想知道结构是否在宏内部扩展了两次,然后它会定义两种不同的类型而不是一种。但是,标准宏实现只扩展了一次,无论如何使用内置函数更明智。
【解决方案2】:

对于此类细节,维基百科并不是特别可靠的来源。

在这种情况下,结构中最大项的大小形成了一个(相当硬的)上限,整个结构可能被填充到该大小上——但实现是如果它认为合适,可以免费使用更少的填充。在许多情况下,对于“N 位”处理器,可以为特定结构带来任何好处的最大填充将是以下两者中的较小者:1) 结构中的最大项,或 2) 处理器本身的“位数” (因此对于 32 位处理器,您通常不需要/不想填充到大于 32 位的边界,即使对于大于该值的数据项也是如此)。

【讨论】:

  • 不,维基百科的措辞是对的,它只取决于一个词。请参阅@Dietrich 的回答。
【解决方案3】:

这是因为在您的情况下,结构与字边界对齐(其中一个字 = 4 个字节)。

【讨论】:

  • @Qiulang:对齐方式与大小不同。对齐必须均分大小 - 因此对于 8 字节双精度,可能的对齐是 1、2、4 和 8。在您的情况下,它显然是 4。
  • @Qiulang - 仔细阅读:“...所有成员的 alignments 的最小公倍数...”不是 sizes i> 个成员,它们的 对齐。数据类型可以有很大的尺寸,但不需要完全对齐到那个尺寸。在 32 位架构中,int64_t 不会因为与 8 字节对齐而获得任何性能优势,因为不会有任何 8 字节指令对其进行操作。所以只需要4字节对齐。
  • 感谢 cmets,正如我上面提到的“双(8 字节)在 Windows 上将是 8 字节对齐,在 Linux 上是 4 字节对齐”。我之前在window上测试过,所以我觉得double的对齐方式是8。MSDN也证实了这一点,msdn.microsoft.com/en-us/library/aa296569%28v=vs.60%29.aspx。所以我错误地认为 linux 也是如此。
  • @caf "对齐方式必须均分大小" 不,不必。 10 字节扩展双精度通常与 4 字节边界对齐。
  • @Pascal Cuoq:是的,确实如此。如果您有一个这样的 10 字节扩展双精度数组,并且 a[0] 在 4 字节边界上对齐,那么 a[1] 将仅在 2 字节边界上对齐。如果类型需要 4 字节对齐,那么它的大小必须是这个的倍数 - 所以即使只有 10 个字节是有意义的,它也需要包含 2 个填充字节才能使其大小达到 12。
猜你喜欢
  • 2016-09-18
  • 2019-03-27
  • 2015-09-23
  • 2016-09-18
  • 1970-01-01
  • 2018-07-03
  • 2015-04-25
  • 2018-11-11
  • 2013-10-29
相关资源
最近更新 更多