检查联合实例之间的相等性的正确方法是什么?

mat*_*975 6 c c++ unions

我有一个多线程应用程序,它将数据存储为以下联合的实例数组

union unMember {
    float fData;
    unsigned int uiData;
};
Run Code Online (Sandbox Code Playgroud)

存储此数组的对象知道联合中的数据是什么类型,因此在检索正确类型时我不会遇到UB问题.但是在程序的其他部分,我需要测试这两个联合实例之间的相等性,并且在这部分代码中,真正的内部数据类型是未知的.结果是我无法使用这种方法测试联合的相等性

  unMember un1;
  unMember un2;
  if (un1 == un2) {
     // do stuff
  }
Run Code Online (Sandbox Code Playgroud)

因为我得到编译错误.因此,我只是比较联合的浮动部分

  if (un1.fData == un2.fData) {
     // compiles but is it valid?
  }
Run Code Online (Sandbox Code Playgroud)

现在考虑到我已经读过它是UB访问一个联盟的任何部分而不是最后写的那部分(这是繁琐的写,但我可以想到没有更明确的方式来说这个)我想知道代码是否以上是检查我的联合实例的相等性的有效方法?

这让我意识到内部我不知道工会是如何运作的.我曾假设数据只是存储为一个位模式,你可以根据你所喜欢的方式解释它,具体取决于联合中列出的类型.如果不是这样,那么测试两个联合实例的相等性的安全/正确方法是什么?

最后,我的应用程序是用C++编写的,但我意识到工会也是C的一部分,那么这两种语言对它们的处理方式有何不同?

LSe*_*rni 8

通常,您需要预先添加当前联合类型的某种指示符:

struct myData
{
    int dataType;
    union {
        ...
    } u;
}
Run Code Online (Sandbox Code Playgroud)

然后:

if (un1.dataType != un2.dataType)
    return (1 == 0);
switch(un1.dataType)
{
    case TYPE_1:
        return (un1.u.type1 == un2.u.type1);
    case TYPE_2:
        ...
}
Run Code Online (Sandbox Code Playgroud)

无论如何,语法

if (un1.fData == un2.fData) {
    // compiles but is it valid?
}
Run Code Online (Sandbox Code Playgroud)

哪个编译并且有效,可能由于两个原因而无法工作.一个是,正如你所说,也许un2包含一个整数而不是一个浮点.但在这种情况下,平等的测试正常终将以失败告终.第二个是两个结构都有一个浮点,它们代表相同的数字,并有轻微的机器错误.然后测试将告诉你数字是不同的(它们是一点一点),而它们的"含义"是相同的.

通常比较浮点数

if (dabs(f1 - f2) < error)
Run Code Online (Sandbox Code Playgroud)

避免这个陷阱.