结构对齐和类型重新解释 [英] Struct alignment and type reinterpretation
问题描述
假设我有两种类型A和B.
Lets say I have two types A and B.
然后我创建这个类型
struct Pair{
A a;
B b;
};
现在我有一个这样的功能。
Now I have a function such as this.
void function(Pair& pair);
并假设 function
使用 a
部分。
然后是未定义的行为,以这种方式使用和调用函数?
Then is it undefined behavior to use and call the function in this way?
A a;
function(reinterpret_cast<Pair&>(a));
我知道编译器可以在成员之后插入填充字节,但是它也可以在第一个成员?
I know that a compiler may insert padding bytes after a member but can it also do it before the first member?
推荐答案
我认为它是定义的行为,假设 Pair
-布局。否则,它是未定义的行为。
I think it's defined behavior, assuming Pair
is standard-layout. Otherwise, it's undefined behavior.
首先,标准布局类及其第一个成员共享一个地址。在[basic.compound](澄清早期规则)中的新措辞如下:
First, a standard layout class and its first member share an address. The new wording in [basic.compound] (which clarifies earlier rules) reads:
两个对象 如果符合以下条件,则 可以互换:
* [...]
* one是一个标准布局类对象另一个是该对象的第一个非静态数据成员,
或,[...]
* [...]
如果两个对象指针可互换,那么它们具有相同的地址,并且可以通过reinterpret_cast $获得指向另一个的指针的
指针c $ c>(5.2.10)。
Two objects a and b are pointer-interconvertible if:
* [...]
* one is a standard-layout class object and the other is the first non-static data member of that object, or, [...]
* [...]
If two objects are pointer-interconvertible, then they have the same address, and it is possible to obtain a pointer to one from a pointer to the other via areinterpret_cast
(5.2.10).
也来自[class.mem]:
Also from [class.mem]:
如果标准布局类对象具有任何非静态数据成员,则其地址与其第一个非静态数据成员的地址
相同。否则,其地址与其第一个基类
子对象(如果有)的地址相同。
If a standard-layout class object has any non-static data members, its address is the same as the address of its first non-static data member. Otherwise, its address is the same as the address of its first base class subobject (if any).
reinterpret_cast
从 A
到配对
如果然后 function
只访问 a
对象,那么访问良好定义, $ c> A 是0,所以行为等同于 function
采取 A&
。显然,对 b
的任何访问都是未定义的。
So the reinterpret_cast
from A
to Pair
is fine. If then function
only ever access the a
object, then that access well-defined, as the offset of A
is 0, so the behavior is equivalent to having function
take an A&
directly. Any access to the b
would be undefined, obviously.
但,虽然我相信代码是定义的行为,这是一个坏主意。它定义的行为 NOW ,但有人有一天可能会改变 function
来引用 pair.b
然后你在一个痛苦的世界。这很容易写:
However, while I believe the code is defined behavior, it's a bad idea. It's defined behavior NOW, but somebody someday might change function
to refer to pair.b
and then you're in a world of pain. It'd be a lot easier to simply write:
void function(A& a) { ... }
void function(Pair& p) { function(p.a); }
并直接调用 function
a
。
这篇关于结构对齐和类型重新解释的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!