2

假设我有以下 C++ 代码:

struct something
{
  // ...
  union { int size, length; };
  // ...
};

这将创建两个struct访问相同值的成员:sizelength

将这两个成员视为完整的别名(即设置大小,然后访问长度,反之亦然)是未定义的行为吗?有没有“更好”的方式来实现这种行为,或者这是一个可以接受的实现方式?

4

3 回答 3

5

这不是未定义的行为。联合中的两个别名都将访问内存中的相同位置。见下文:

§9.2/18如果一个标准布局联合包含两个或多个共享一个公共初始序列的标准布局结构,并且如果标准布局联合对象当前包含这些标准布局结构之一,则允许检查公共其中任何一个的初始部分。如果对应的成员具有布局兼容的类型,并且对于一个或多个初始成员的序列,两个标准布局结构都不是位域或两者都是具有相同宽度的位域,则两个标准布局结构共享一个共同的初始序列。

如果类型具有不同的初始序列,则未定义。

于 2013-03-07T17:33:32.420 回答
5

是的,这是允许的并且定义明确。根据§3.10 [basic.lval]:

10/如果程序尝试通过非下列类型之一的左值访问对象的存储值,则行为未定义:

— 对象的动态类型

[...]

由于在这里我们存储 anint并通过 an 读取int,我们通过与对象相同的动态类型的 glvalue 访问对象,因此一切都很好。


对于共享相同前缀的结构,标准中甚至还有一个特殊警告。或者,在标准的标准布局类型中,共享一个共同的初始序列

§9.2/18如果一个标准布局联合包含两个或多个共享一个公共初始序列的标准布局结构,并且如果标准布局联合对象当前包含这些标准布局结构之一,则允许检查公共其中任何一个的初始部分。如果对应的成员具有布局兼容的类型,并且对于一个或多个初始成员的序列,两个标准布局结构都不是位域或两者都是具有相同宽度的位域,则两个标准布局结构共享一个共同的初始序列。

那是:

struct A { unsigned size; char type; };
struct B { unsigned length; unsigned capacity; };

union { A a; B b; } x;

assert(x.a.size == x.b.length);

编辑:鉴于这int不是struct(也不是class)我恐怕它实际上没有正式定义(我当然在标准中看不到任何东西),但在实践中应该是安全的......我已经把问题带到了 isocpp 论坛; 你可能找到了一个洞。

编辑:在上述讨论之后,我看到了§3.10/10。

于 2013-03-07T17:40:32.420 回答
0

值将相同。如果将 5 分配给 size,则长度也将为 5。

于 2013-03-07T17:34:16.140 回答