当a和b是并集时,a=b的行为是什么? 至于我理解关于工会的C和C++标准,如果我试图访问一个与实际写入的字段不同的联合字段,则在技术上是未定义的行为。最近,我一直在审查其他人编写的一些类似于以下内容的旧代码: union myunion { float myfloat; unsigned int myuint; }; myunion a; a.myfloat = 1.01; myunion b = a;

当a和b是并集时,a=b的行为是什么? 至于我理解关于工会的C和C++标准,如果我试图访问一个与实际写入的字段不同的联合字段,则在技术上是未定义的行为。最近,我一直在审查其他人编写的一些类似于以下内容的旧代码: union myunion { float myfloat; unsigned int myuint; }; myunion a; a.myfloat = 1.01; myunion b = a;,c++,c,unions,C++,C,Unions,简而言之,我试图找出以这种方式对并集使用赋值运算符是否实际上是定义良好的行为。当我自己编写这样的代码时,我会尽力存储union实例所使用的字段类型,并确保我只读取或写入这个值。我猜想,使用上面的赋值运算符可能只会导致按位复制(因为在本例中,字段大小相等),因为在调试器中单步执行代码表明这就是正在发生的情况。这段代码一直显示出一些微妙的错误,因此我很想通过以这种方式直接将一个联合分配给另一个联合来发现UB是否存在任何固有的风险。。行为定义明确 b现在的值与a相同,myfloat的值为1.01。赋值

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

。行为定义明确

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


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

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

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



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

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

在C++11之前的版本中,
联合只能包含POD(或类似的内容)
这些限制的设计使得按位复制可以工作。在C++11中,某些限制已被取消,但如果您违反了旧的限制,复制和赋值将被删除(除非您自己定义运算符)。

您已经自己回答了。:)联合赋值将导致按位复制。即使元素的大小不相等,如果所有成员都是POD,则按位复制也会起作用。(这以前是必需的。)我相信当联合或结构包含未命名的成员时,会有一些特殊规则?如果有人能澄清这些成员的情况,那就太好了。另外,填充字节会发生什么情况?“如果我试图访问与实际写入的字段不同的联合的特定字段,这在技术上是未定义的行为”C99TC3中的脚注82要宽容一点。@Jay:指定联合赋值不是为了产生按位复制。您自己已经回答了。:)联合赋值将导致按位复制。即使元素的大小不相等,如果所有成员都是POD,则按位复制也会起作用。(这以前是必需的。)我相信当联合或结构包含未命名的成员时,会有一些特殊规则?如果有人能澄清这些成员的情况,那就太好了。另外,填充字节会发生什么情况?“如果我试图访问联合的特定字段,而该字段与实际写入的字段不同,这在技术上是未定义的行为。”C99TC3中的脚注82比这更宽容一些。@Jay:联合赋值并不是为了产生按位复制而指定的。@a=b;然后在(a==b)之后,你永远不能保证你的结果是真的。这取决于您使用的编译器。编译器的比较运算符可能会以不同方式处理插入到联合体中的可能填充字节。比较浮点值“没有一般问题”。浮动有一个完美定义的顺序。无论是ab还是ab,结果都是确定的,赋值后两个值完全相等。您可能会被某些不精确浮点运算(例如1/3)所混淆,这与比较完全不同。@史蒂芬没有用于工会的自动运算符==,但是对于C++,您可以编写过载。联合本身不包含所设置的特定成员,因此,如果两个联合不包含相同的数据类型,则它们是未定义的。@MSalters:只有浮点数(包括无穷大)的数值是有序的。与NaN的比较返回false,即使在比较NaN是否与自身相等时也是如此。但这与是否存在任何浮点错误无关