结构对齐 C/C++
Posted
技术标签:
【中文标题】结构对齐 C/C++【英文标题】:struct alignment C/C++ 【发布时间】:2013-07-24 14:02:41 【问题描述】:在 c/c++ 中(我假设它们在这方面是相同的),如果我有以下内容:
struct S
T a;
.
.
.
s;
以下内容是否保证为真?
(void*)&s == (void*)&s.a;
或者换句话说,是否有任何保证在第一个成员之前没有填充?
【问题讨论】:
他们在这方面不一样 @MooingDuck:嗯,这取决于...
是什么。对于相同的结构定义,C++ 会以与 C 相同的方式对待它(C 结构始终满足 C++ standard-layout 要求)。
【参考方案1】:
在 C 中,是的,它们是相同的地址。简单明了。
在 C++ 中,不,它们不是同一个地址。基类可以(而且我怀疑,确实)出现在所有成员之前,并且虚拟成员函数通常会在某处将隐藏数据添加到结构中。更令人困惑的是,C++ 编译器还可以随意重新排列成员,除非该类是标准布局类型(尽管我不知道任何编译器都会这样做)
最后,如果 C++ 结构由标准布局类型组成,不包含基类或虚函数,并且所有成员都具有相同的可见性,可能还有其他我忘记的限制,那么 它依赖于 C 规则,并要求第一个成员与对象本身位于同一地址。
第 9.2/7 节
标准布局类是这样的类: — 没有非标准布局类(或此类类型的数组)或引用类型的非静态数据成员, — 没有虚函数 (10.3) 和虚基类 (10.1), — 对所有非静态数据成员具有相同的访问控制(第 11 条), — 没有非标准布局的基类, — 要么在派生最多的类中没有非静态数据成员,并且最多有一个具有非静态数据成员的基类,要么没有具有非静态数据成员的基类,并且 — 没有与第一个非静态数据成员相同类型的基类。
第 9.2/20 节
一个指向标准布局结构对象的指针,使用 reinterpret_cast 适当地转换,指向它的初始成员(或者如果该成员是位字段,则指向它所在的单元),反之亦然。 [注意:因此,标准布局结构对象中可能存在未命名的填充,但不是在其开头,这是实现适当对齐所必需的。 ——尾注]
【讨论】:
“标准布局类”也称为POD(“plain old data type”),可以使用std::is_pod进行验证。 @marcin_j:不。POD 需要 standard-layout 和 trivial construction/copy/destruction。一个类可以有非默认的构造函数和析构函数以及其他特殊成员,并且仍然是标准布局。 感谢您的澄清,我看到可以使用 std::is_standard_layout是的。
保证在 C 和 C++ 中的第一个结构成员之前没有填充(如果它是 POD)。
C 引用:
(C11, 6.7.2.1p15) "结构对象中可能有未命名的填充,但不是在其开头。"
C++ 引用:
(C++11, 9.2p20) “因此,标准布局结构对象中可能有未命名的填充,但不是在其开头,这是实现适当对齐所必需的”
【讨论】:
在 C++ 中,只有当它是 POD 时才能保证。 @n.m.添加了对 C++ 的引用和对 POD 的提及。谢谢 @n.m.如果什么是 POD?结构体S
或成员T
?
比较 &s == &s.a
是非法的,因为 struct S*
和 T*
不是兼容的类型。但是(void*)&s == (void*)&s.a
@huseyintugrulbuyukisik 如果您的意思是在运行时移动?那就不要。 编译器可以重新排列它们,但运行时不会。没错,它不能,因为它不知道对象的位置。以上是关于结构对齐 C/C++的主要内容,如果未能解决你的问题,请参考以下文章