假设我有以下C ++代码:
struct something
{
// ...
union { int size, length; };
// ...
};
这会创建struct
的两个成员,这两个成员访问相同的值:size
和length
。
将两个成员视为完整别名(即设置大小,然后访问长度,反之亦然)是不确定的行为?有没有“更好”的方法来实现这种行为,或者这是一种可接受的实现?
答案 0 :(得分:5)
这不是未定义的行为。联合中的两个别名都将访问内存中的相同位置。见下文:
§9.2/ 18 如果标准布局联合包含两个或更多 标准布局结构共享一个共同的初始序列,如果 标准布局联合对象当前包含其中一个 标准布局结构,允许检查公共初始 他们中的任何一个。两个标准布局结构共享一个共同点 初始序列,如果相应的成员具有布局兼容类型 并且要么两个成员都不是位字段,要么两者都是位字段 一个或多个初始成员序列的宽度相同。
如果类型具有不同的初始序列,则未定义。
答案 1 :(得分:4)
是的,这是允许的并且定义明确。根据§3.10[basic.lval]:
10 / 如果程序试图通过以下类型之一以外的glvalue访问对象的存储值,则行为未定义:
- 对象的动态类型
[...]
由于这里我们存储int
并通读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。
答案 2 :(得分:0)
值将相同。如果为尺寸指定5,则长度也将为5.