什么是工会?

最近我在windows上工作,我发现许多数据结构被定义为带有union作为成员变量的struct 。 例如,Windows中的EVT_VARIANT

我不明白这背后的目的是什么。

struct包含union成员时,它通常作为节省空间的机制完成。 如果struct可以是某些子类型,只有某些成员才有效,那么union是一种不浪费空间的好方法。

例如

 enum NumberKind { Integer, FloatingPoint }; struct Number { NumberKind kind; union { int integerValue; float floatValue; }; }; 

在这种情况下,我定义了一个struct Number,它可以有类型的数值:浮点和整数。 同时拥有两者并不是因为两个成员总是被定义而浪费空间是无效的我创建了一个union ,它使两者的存储量等于最大的大小。

根据要求提供上面的样品使用

 void PrintNumber(Number value) { if (value.kind == Integer) { printf("%d\n", value.integerValue); } else { printf("%f\n", value.floatValue); } } 

想象一下,你有一个包含数据包的结构。 数据包中的数据可以是几种不同的类型,因此您将类型存储在名为type的成员中。 因此,要读取此数据包中的数据,首先检查类型,然后读取相应的数据成员,该成员应包含数据包中的数据。

没有联合,数据结构将如下所示:

 struct data { type_t type; int number; char * string; double fraction; long long big_number; } 

这将是一个相当大的数据结构。 它使用足够的空间来存储每种可能的数据类型之一。 如果您在任何时间点肯定只有其中一个成员包含有用信息,那就有点不必要了。

如果我们使用工会:

 struct data { type_t type; union payload { int number; char * string; double fraction; long long big_number; } } 

然后struct只包含足够的空间来存储类型加上一个有效负载成员(即你将分配一个等于type_t大小的内存量加上最大可能的有效负载成员的大小)。 这节省了大量空间并且效率更高。

但是,您必须要小心,因为如果有效负载包含int,您仍然可以将其读作double。 当程序试图错误地解释数据时,您可能会得到非常奇怪的数字

作为64KB相当大的内存时代的遗留物,你有一个C ++工具,允许多个变量共享相同的内存(但显然,不是同时)。 这称为联合,有四种基本方法可供您使用:

  • 您可以使用它,以便变量A在程序中的某一点占用一块内存,后来由另一个不同类型的变量B占用,因为不再需要A. 我建议你不要这样做。 在这样的安排中隐含的错误风险是不值得的。 您可以通过动态分配内存来实现相同的效果。

  • 或者,您可能在程序中遇到需要大量数据的情况,但您不知道数据类型将在执行之前 – 它将由输入数据确定。 我还建议您在这种情况下不使用联合,因为您可以使用几个不同类型的指针来实现相同的结果,并再次动态分配内存。

  • 工会的第三种可能用途是您可能需要现在和将来 – 当您想要以两种或更多种方式解释相同的数据时。 如果您有一个long类型的变量,并且您希望将其视为short类型的两个值,则可能会发生这种情况。 Windows有时会在传递给函数的long类型的单个参数中打包两个短值。 当您想要将包含数字数据的内存块视为字节字符串时,会出现另一个实例,只是为了移动它。

  • 您可以使用union作为将对象或数据值传递到您事先不知道其类型的位置的方法。 联盟可以提供存储您可能具有的任何一种类型的联盟。

如果你认为我是一个天才来解释工会是什么以及它的一些可能的应用,我不能因此而受到赞扬。 (:这些信息来自Ivor Horton的Beginning Visual C ++ 2010,我碰巧坐在我的办公桌上。我希望这很有帮助。

当您需要变体样式结构时,通常使用结构技术中的联合。 它通常伴随着类型标识符,用于确定要检查的联合中的哪个项目。 它也以相反的方式出现,例如在* NIX上的Xlib中,它是与结构的联合,第一个成员在所有结构之间相同,定义哪个结构具有您需要的数据。

union意味着您可以将其中一个成员作为其可能的值。 在以下示例中,您将看到每个示例的值。 但是这个联合可以是某个其他结构的成员,只需要指定一个值 – 浮点数或整数,而不是两者。 希望这可以帮助。

  union { float u_f; int u_i; }var; var.u_f = 23.5; printf("value is %f\n", var.u_f); var.u_i = 5; printf("value is %d\n", var.u_i)