最近我正在开发Windows,我发现许多数据结构被定义为struct
,union
作为成员变量。例如,Windows中的EVT_VARIANT
。
我无法理解这背后的目的是什么。
答案 0 :(得分:16)
当struct
包含union
成员时,它通常作为节省空间的机制完成。如果struct
可以是某些子类型,只有某些成员才有效,那么union
是不浪费空间的好方法。
例如
enum NumberKind {
Integer,
FloatingPoint
};
struct Number {
NumberKind kind;
union {
int integerValue;
float floatValue;
};
};
在这种情况下,我定义了一个struct
数字,它可以包含数值类型:浮点数和整数。同时拥有两者并不是有效而不是通过让两个成员始终定义而浪费空间我创建了union
,这使得两者的存储量等于最大值的大小。
按要求使用上面的示例
void PrintNumber(Number value) {
if (value.kind == Integer) {
printf("%d\n", value.integerValue);
} else {
printf("%f\n", value.floatValue);
}
}
答案 1 :(得分:3)
想象一下,你有一个包含数据包的结构。数据包中的数据可以是几种不同的类型,因此您将类型存储在名为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。当你的程序试图错误地解释数据时,你可能会得到非常奇怪的数字
答案 2 :(得分:3)
作为64KB内存相当多的日子的遗物,你有一个C ++工具,允许多个变量共享相同的内存(但显然,不是同时)。这称为联合,有四种基本方法可供您使用:
您可以使用它,以便变量A在程序中的某一点占用一块内存,后来由另一个不同类型的变量B占用,因为不再需要A.我建议你不要这样做。在这种安排中隐含的错误风险是不值得的。您可以通过动态分配内存来实现相同的效果。
或者,您可能会遇到需要大量数据的程序,但您不知道执行之前的数据类型是什么 - 它将由输入确定数据。我还建议你不要在这种情况下使用联合,因为你可以使用几个不同类型的指针来实现相同的结果,并再次动态分配内存。
联合的第三种可能用途是您可能需要现在和将来再次使用 - 当您想要以两种或更多种方式解释相同的数据时。如果您有一个long类型的变量,并且您希望将其视为short类型的两个值,则可能会发生这种情况。 Windows有时会在传递给函数的long类型的单个参数中打包两个短值。当你想将包含数字数据的内存块视为一串字节时,就会出现另一个例子,只是为了移动它。
您可以使用union作为将对象或数据值传递到您事先不知道其类型的位置的方法。联盟可以提供存储您可能具有的任何一种类型的文件。
如果你认为我是一个天才来解释一个联盟是什么以及它的一些可能的应用,我不能因此而受到赞扬。 (:这些信息来自Ivor Horton的Beginning Visual C ++ 2010,我碰巧坐在我的办公桌上。我希望这很有帮助。
答案 3 :(得分:1)
结构技术中的联合通常在需要变体样式结构时使用。它通常伴随着类型标识符,用于确定要检查的联合中的哪个项目。它也以相反的方式出现,例如在* NIX上的Xlib中,它是与结构的联合,第一个成员在所有结构之间相同,定义哪个结构具有您需要的数据。
答案 4 :(得分:0)
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)