2

据我了解有关联合的 C 和 C++ 标准,如果我尝试访问与实际写入的字段不同的联合的特定字段,这在技术上是未定义的行为。最近一直在查看别人写的一些旧代码,类似如下:

 union myunion {
     float myfloat;
     unsigned int myuint;
 };

 myunion a;
 a.myfloat = 1.01;

 myunion b = a;

简而言之,我试图找出以这种方式在联合上使用赋值运算符是否实际上是明确定义的行为。当我自己编写这样的代码时,我会努力存储联合实例主动使用的字段类型,并确保我只读取或写入该值。我猜测使用上面的赋值运算符可能只会导致按位复制(因为在此示例中,字段大小相同),因为在调试器中单步执行代码表明这是正在发生的事情。这段代码一直表现出微妙的错误,所以我很想通过以这种方式直接将联合分配给另一个联合来找出在 UB 意义上是否存在任何固有风险。

4

2 回答 2

2

正如你所期望的那样。行为是明确定义的。

b 现在与 a 具有相同的值,myfloat 值为 1.01。赋值是按位的。如果您想以“安全”的方式比较 a 和 b,您可以进行按位比较。(operator==在 float 成员上使用不太安全,部分原因是如果其中一个实际上不包含浮点数,它就是 UB,部分原因是比较浮点数的问题)。实际上并没有为联合自动定义比较相等性,因此您必须编写重载。

联合中总是只有允许分配工作的原始类型。唯一的问题可能是类型是否可以是指针并且您在某处管理该指针。然后,如果您有两个持有此指针的联合实例,则必须小心。(但是,如果您甚至有一个包含指针的常规变量,这也适用)。

于 2013-01-30T12:23:21.343 回答
2

在 C++11 之前的版本中,union只能包含 POD(或类似的东西)——限制的设计使得按位复制可以工作。在 C++11 中,一些限制已经解除,但是如果你违反了旧的限制,复制和赋值都会被删除(除非你自己定义了操作符)。

于 2013-01-30T12:26:04.107 回答