struct alignment C/C++

Bar*_*uch 31 c c++ memory-layout

在c/c ++中(我假设它们在这方面是相同的),如果我有以下内容:

struct S {
  T a;
  .
  .
  .
} s;
Run Code Online (Sandbox Code Playgroud)

以下是否保证是真的?

(void*)&s == (void*)&s.a;
Run Code Online (Sandbox Code Playgroud)

或者换句话说,是否有任何保证第一个成员之前没有填充?

Moo*_*uck 44

在C中,是的,它们是相同的地址.简单明了.


在C++中,不,它们不是同一个地址.基类可以(我怀疑,确实)来到所有成员之前,而虚拟成员函数通常会将隐藏数据添加到某个地方的结构中.更令人困惑的是,C++编译器也可以随意重新排列成员,除非该类是标准布局类型(虽然我不知道任何编译器都这样做)

最后,如果C++结构由标准布局类型组成,不包含基类和虚函数,并且所有成员都具有相同的可见性,并且可能还有其他我忘记的限制,那么它将依赖于C规则,并且需要第一个成员与对象本身位于同一地址.

§9.2/ 7

标准布局类是一个类:
- 没有类型为非标准布局类(或此类类型的数组)或引用的非静态数据成员,
- 没有虚函数(10.3)且没有虚基类( 10.1),
- 对所有非静态数据成员具有相同的访问控制(第11条),
- 没有非标准布局基类,
- 在最派生类中没有非静态数据成员,最多只有一个具有非静态数据成员的基类,或者没有具有非静态数据成员的
基类,并且- 没有与第一个非静态数据成员相同类型的基类.

§9.2/ 20

指向标准布局结构对象的指针,使用reinterpret_cast进行适当转换,指向其初始成员(或者如果该成员是位字段,则指向它所在的单元),反之亦然.[注意:因此,在标准布局结构对象中可能存在未命名的填充,但不是在其开头,以实现适当的对齐. - 尾注]

  • @marcin_j:否.POD需要*标准布局*和*普通构造/复制/销毁*.一个类可以有非默认的构造函数和析构函数以及其他特殊成员,但仍然是*standard-layout*. (10认同)

oua*_*uah 16

是的.

保证在C和C++中的第一个结构成员之前没有填充(如果它是POD).

C报价:

(C11,6.7.2.1p15)"结构对象中可能有未命名的填充,但不是在它的开头."

C++引用:

(C++ 11,9.2p20)"因此,在标准布局结构对象中可能存在未命名的填充,但在开始时可能没有,以实现适当的对齐"

  • 比较`&s ==&s.a`是非法的,因为`struct S*`和`T*`是不兼容的类型.但是`(void*)&s ==(void*)&s.a` (8认同)
  • 在C++中,只有它是POD才能保证. (6认同)