提问人:cerveka2 提问时间:8/31/2022 最后编辑:timraucerveka2 更新时间:9/19/2022 访问量:466
分配后工会的活跃成员
Active member of an union after assignment
问:
假设 ,我有以下代码片段:sizeof( int ) == sizeof( float )
union U{
int i;
float f;
};
U u1, u2;
u1.i = 1; //i is the active member of u1
u2.f = 1.0f; //f is the active member of u2
u1 = u2;
我的问题:
- 它有明确的行为吗?如果不是,为什么?
- 分配后的活跃成员是什么,为什么?
u1
- 分配后可以从哪个成员中读取而不会引起 UB,为什么?
u1
答:
13赞
AProgrammer
8/31/2022
#1
- 它有明确的行为吗?如果不是,为什么?
它定义了行为。分配副本的值,对我来说,联合的值是活动成员的指定(尽管该部分没有表示,因此无法检查,但它决定了什么是 UB,什么不是)和活动成员的值(如果有的话)。u2
- 分配后 u1 的活跃成员是什么,为什么?
f,见上文。
分配后可以从哪个 u1 成员中读取而不会引起 UB,为什么?
f.通常,在 C++ 中,只有没有 UB 的情况下才能读取联合的活动成员。结构的并集有一个特殊的规则,其中这些结构具有共同的初始序列。注意:C更宽松,并且定义了实现(也许完全定义)了一些在C++中未定义的情况,我可能错过了C++中的一些更改,以使其与C更兼容。
如果有人想查找标准,我建议从 class.copy.assign/13 开始。
评论
0赞
H.S.
8/31/2022
从第一点开始,与为 和 类型赋值相同。它是否适用于所有情况(无论价值如何)?u1 = u2
float
int
u2.f
0赞
AProgrammer
8/31/2022
我的理解(我没有时间用标准引用来支持,我对那个游戏很生疏,不得不重新发现我曾经知道的东西),是结束 , 一个类型的对象的生存时间,开始 , 同一地址的类型对象的生存期,分配给该对象。只要有效,分配就有效。u1 = u2
u1.i
int
u1.f
float
u2.f
u2.f
2赞
Peter Cordes
9/1/2022
请注意,许多 C++ 实现确实定义了读取非活动联合成员的行为。例如,所有实现 C 和 C++ 的 GNU 扩展的编译器,如 GCC、clang 和 ICC,都像 C99 一样定义它。ISO C++ 未定义行为并不会阻止实现定义它。GCC 引用 C89/C90 标准来描述它的方式似乎确实表明 C89 需要实现来选择某些行为,但这是古老的;现代 C 语言定义了它
1赞
Peter Cordes
9/1/2022
(“实施定义的行为”具有特定的含义,即 ISO 标准要求实施以某种方式定义的行为。我不记得 C89 定义了联合类型双关语实现,这是一个非常晦涩难懂的观点,所以我只是想为未来的读者做出这种区分。C99 及更高版本完全定义了该行为。许多但不是全部的现代C++编译器也定义了行为,但ISO C++没有。所以+1)
0赞
supercat
9/2/2022
@PeterCordes:查看 C89 缺陷报告 #028,我认为没有明确说明“实现定义”应该意味着什么。在考虑类似 : 时,缺陷报告 #028 指出,由于行为或写入一个成员并读取另一个成员是实现定义的,因此不允许执行此类操作,因此通过指针执行此类操作将产生未定义的行为。只有当IDB和UB接近同义词时,这种说法才有意义。int test(void) { union U { float f; int i; } u; int *fp = &u.f; *fp = 1.0; int *ip = &u.i; return *ip; };
评论
float
u1 = u2;
u1
u2