你能把一个工会成员的值分配给另一个吗

Can you assign the value of one union member to another?

本文关键字:成员 分配 另一个 一个      更新时间:2023-10-16

考虑以下代码片段:

union
{
int a;
float b;
};
a = /* ... */;
b = a;               // is this UB?
b = b + something;

将一个工会成员分配给另一个工会会员有效吗?

不幸的是,我相信这个问题的答案是,在C++中,对并集的这个操作没有得到充分的指定,尽管自分配是完全可以的。

自分配是一种定义良好的行为,如果我们查看C++标准草案1.9程序执行15段有以下示例:

void f(int, int);
void g(int i, int* v) {
i = v[i++]; // the behavior is undefined
i = 7, i++, i++; // i becomes 9
i = i++ + 1; // the behavior is undefined
i = i + 1; // the value of i is incremented
f(i = -1, i = -1); // the behavior is undefined
}

并且在CCD_ 2示例中涵盖了自分配。

这里的问题是,与支持C++中类型双关的C89 forward不同,这一点尚不清楚。我们只知道:

在联合中,在任何时候最多可以有一个非静态数据成员处于活动状态

但由于WG21 UB研究组邮件列表中的讨论表明这一概念还没有得到很好的理解,我们有以下评论:

虽然标准使用术语"活动字段",但并未将其定义为

并指出了这个非规范性注释:

注意:通常,必须使用显式析构函数调用和放置新运算符来更改联合的活动成员。--尾钞

所以我们不得不怀疑是否:

b = a;

是否使b成为活动成员?我不知道,也看不出有什么方法可以用任何当前版本的标准草案来证明这一点。

尽管在所有的实用性中,大多数现代编译器(例如gcc)都支持C++中的类型双关,这意味着绕过了活动成员的整个概念。

我认为,除非源变量和目标变量是相同的类型,否则C中的Undefined Behavior就是这样,我认为没有理由期望C++以任何不同的方式处理它。给定long long *x,*y;,一些编译器可能会通过生成代码读取所有*y、计算结果并将其存储到*x来处理类似*x = *y >>8;的语句,但编译器可能完全合法地编写代码,将*y的部分单独复制到*x。该标准明确规定,如果*x和*y是指向同一类型的同一对象的指针,编译器必须确保在计算中仍然需要该部分时,值的任何部分都不会被覆盖,但在其他情况下编译器不需要处理混叠。