C++中结构体的对齐方式

4

本文讨论的范围是x86架构。
例如,我们有一个如下所示的结构体:

struct X{
   int    a;   
   char   b; 
               // compiler will pad 3 bytes here
   double c;
};
X x;

我认为x的对齐应该是它的最大成员,即在这种情况下是double,它占用8字节,所以&x应该是8的倍数,我对吗?

然而,在一些测试之后,我的编译器(msvc 2013)说&x也可以是4的倍数,但不是8

这是否意味着&x.c也将是4的倍数?

我在哪里误解了?


2
这取决于编译器。例如,请参见https://dev59.com/BG035IYBdhLWcg3wef9y - Nathan Monteleone
我非常想看到一个除了四以外的倍数,但不是八。开玩笑的,虽然在跨平台兼容性方面你不能依赖太多,但你的系统很可能会指定这种类型的事情或遵守规范。例如,x86的System V规范指定double对齐到四个字节,而不是八个字节。 - Stuart Olsen
3个回答

3
C和C++标准对于对齐方式并未给出任何建议[或者至少没有明确的规则]。每个编译器(当然也包括编译器的目标)都需要确定一个好的策略。通常情况下,这种策略适用于目标... ;)
由于x86的FPU [包括标量模式下的SSE]可以从任意字节地址读取“double”,而且我认为在bc元素之间添加超过3个字节或将整个结构体对齐到超过4个字节都没有直接的好处。做更多就会浪费内存。
在其他一些架构中,这可能会带来很大的好处(或者是目标要求正确操作的要求),因此会将整个struct对齐到8个字节。

2
在VC中的结构对齐是一个编译器选项,/Zp可以确定结构体打包时的字节边界。这通常是高级选项,除非在不寻常的用例(例如执行块数据的memcpy以进行网络传输)中使用。请检查项目的属性页面以查看对齐方式。

http://msdn.microsoft.com/en-us/library/xh3e3fd0.aspx


1

一般来说,你不能太多地关注struct的大小、对齐方式或者打包情况。而"一般"指的是根据你所选择的C++标准。

问题在于:

  • intchardouble的大小没有被C++标准定义,标准只是设置了一些最小要求,你将得到什么取决于实现
  • 对齐不仅依赖于编译器的实现,有时甚至依赖于你传递的标志集和你的目标硬件,打包对CPU缓存非常重要,有些指令甚至需要不同的填充,这也取决于你在struct中放置了什么以及你如何编写它。
因此,对于这种操作,您必须严格遵循所选择的编译器的文档,并深入了解其提供的功能,例如在此处,您可以找到有关如何在gccmsvc中打包数据的概述(链接)

没有什么的。这是定义1。请查看我在备注中提供的链接。 - Jan Herrmann
从您发布的链接中,@JanHerrmann提到:“根据计算机架构,一个字节可能由8个或更多位组成”,现在请告诉我们这3种类型在C++标准中有多大。如果您能够以位和对齐方式来描述,那么您就赢了。 - user2485710
根据我提供的链接,sizeof 在标准中被定义为对于 charsigned charunsigned char 返回 1。而 alignof(http://en.cppreference.com/w/cpp/language/alignof)返回最小对齐方式。`int` 和 double 的大小是实现定义的,但 char 的大小不是。因此,你的第一个观点是不正确的。 - Jan Herrmann
@JanHerrmann 请再仔细阅读,你错了,sizeof运算符返回字节,即使你知道一个东西是1个字节,但你无法定义一个字节的大小,你对类型的大小一无所知,就这么简单。 - user2485710
让我们在聊天中继续这个讨论 - Jan Herrmann

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