结构对齐和类型重新解释 [英] Struct alignment and type reinterpretation

查看:128
本文介绍了结构对齐和类型重新解释的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有两种类型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 a reinterpret_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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆