结构对齐和类型重新解释

时间:2016-09-20 16:21:16

标签: c++ struct undefined-behavior

假设我有两种类型A和B.

然后我做这个类型

struct Pair{
    A a;
    B b;
};

现在我有了这样的功能。

void function(Pair& pair);

我们假设function只会使用该对中的a部分。

然后是使用未定义的行为并以这种方式调用函数吗?

A a;
function(reinterpret_cast<Pair&>(a));

我知道编译器可以在成员之后插入填充字节,但是它也可以在第一个成员之前插入吗?

2 个答案:

答案 0 :(得分:4)

我认为它是定义的行为,假设Pair是标准布局。否则,它是未定义的行为。

首先,标准布局类及其第一个成员共享一个地址。 [basic.compound]中的新措辞(澄清了之前的规则)如下:

  

如果出现以下情况, a b 两个对象指针可互换
  * [...]
  * one是标准布局类对象,另一个是该对象的第一个非静态数据成员,   或者,[...]
  * [...]
  如果两个对象是指针可互换的,那么它们具有相同的地址,并且可以获得   通过reinterpret_cast(5.2.10)指向另一个指针的指针。

同样来自[class.mem]:

  

如果标准布局类对象具有任何非静态数据成员,则其地址与地址相同   其第一个非静态数据成员。否则,其地址与其第一个基类的地址相同   子对象(如果有的话)。

所以从reinterpret_castA的{​​{1}}很好。如果Pair只访问function对象,那么该访问定义良好,因为a的偏移量为0,所以行为等同于A直接function。显然,任何对A&的访问都是不明确的。

然而,虽然我认为代码是定义的行为,但这不是一个好主意。它已定义的行为现在,但有一天某人可能会更改b以引用function,然后您就会陷入痛苦的世界。简单地写一下就容易多了:

pair.b

并直接使用void function(A& a) { ... } void function(Pair& p) { function(p.a); } 致电function

答案 1 :(得分:-1)

是的,它是未定义的行为。

在结构对中,a和b之间可以有填充。对结构成员的赋值可以修改结构中的任何填充。所以对pair.a的赋值可以修改内存,它认为结构中有填充,实际上只有随机内存跟随你占用的内存。