【发布时间】:2021-09-17 14:49:38
【问题描述】:
出于某些测试目的,我需要比较两个联合以查看它们是否相同。将所有成员一一比较就够了吗?
union Data {
int i;
float f;
char* str;
} Data;
bool isSame(union Data left, union Data right)
{
return (left.i == right.i) && (left.f == right.f) && (left.str == right.str);
}
我的预感是,如果一个工会首先包含一个较大的类型,然后切换到一个较小的类型,它可能会失败。我看到一些建议提到将联合包装在一个结构中(比如这里:What is the correct way to check equality between instances of a union?),它跟踪联合当前是哪种数据类型,但我不知道这实际上是如何实现的。我不需要在设置联合值的每个实例中手动设置联合类型吗?
struct myData
{
int dataType;
union {
...
} u;
}
void someFunc()
{
struct myData my_data_value = {0};
my_data_value.u.i = 5;
my_data_value.u.dataType = ENUM_TYPE_INTEGER;
my_data_value.u.f = 5.34;
my_data_value.u.dataType = ENUM_TYPE_FLOAT;
...
}
似乎没有必要将涉及我的联合的所有代码加倍,以便能够对联合值进行完美比较。我是否错过了一些明显的聪明方法来解决这个问题?
【问题讨论】:
-
您想通过比较得出什么结论?某些元素的平等?然后比较它们。占用内存是否相等?然后使用
memcmp -
我认为你最好编写一个函数来比较
myDatas 而不是us。如果dataType不同,您可以从提前退出开始。然后,您可以打开dataType并比较有效的联合成员。我认为这可能是安全性和性能之间的最佳平衡。我已经很久没有使用联合了,但是......如果你不跟踪哪个成员是有效的,那么你可能会遇到比比较其中两个更大的问题。 -
@EugeneSh。如果我通过程序的某些部分推送一些一般数据,我知道它会以联合形式结束(例如 union myData finalData = pushThrough("1234.09")),我想编写一个类似的测试:assert(isSame(1234.09 , finalData) == true),但如果我能概括一下是否在左侧也采用联合,那就太好了,所以我不必对联合中的每种类型进行比较 fcn(例如 isSameFloat( ...),isSameDouble()...,isSameInt()...)。是不是更清楚了?
-
@TimRandall 您是说必须始终将联合包装在结构中吗?我使用联合来包含可能是不同类型的数据,主要是作为一种简化/概括我的代码的方式(所以我不需要为我使用的每种类型创建不同的函数)。当我需要转换数据时,我“知道”数据是什么类型,这样我就可以使用正确的成员,但介于两者之间的只是一些“通用”数据,由联合符号表示。我不知道这是否“正确”,但我发现那一刻我的生活变得更简单了。
-
为了正确使用联合(),您需要知道哪个元素是当前活动的元素。你怎么知道的并不重要。您可以将当前元素 ID 保存在一个结构中,或者根据其他数据即时计算它,或者其他任何东西,但是您需要以某种方式在某个地方拥有这些信息。否则,联合只是一堆毫无意义的比特。 () “正确”是指“没有类型双关语”。类型双关语在技术上是允许的,但它确实把你的联合变成了一堆毫无意义的东西。如果这是您想要的,请与
memcmp进行比较。