最近我在使用Windows时发现,很多数据结构被定义为struct
,并且有union
作为成员变量。例如Windows中的EVT_VARIANT
。
我不理解这样做的目的是什么。
当一个struct
包含union
成员时,通常是为了节省空间。如果这个struct
可以是某些子类型,而只有某些成员是有效的,则使用union
是不浪费空间的好方法。
例如:
enum NumberKind {
Integer,
FloatingPoint
};
struct Number {
NumberKind kind;
union {
int integerValue;
float floatValue;
};
};
在这个场景中,我定义了一个“结构体(Number)”,它可以拥有浮点数和整数类型的数字值。同时拥有浮点数和整数类型是无效的,因此,我创建了一个“联合体(union)”,使得存储最大值的大小等于两者之间的较大值,避免了对内存空间的浪费。void PrintNumber(Number value) {
if (value.kind == Integer) {
printf("%d\n", value.integerValue);
} else {
printf("%f\n", value.floatValue);
}
}
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;
}
}
那么,结构体只包含足够存储类型和其中一个有效载荷成员的空间(即,您将分配与type_t大小加上最大可能有效载荷成员大小相等的内存量)。这样可以节省大量空间并且更加高效。
但是,您必须小心,因为如果有效载荷包含int类型,您仍然可以将其读取为double类型。您的程序尝试错误地解释数据时,您可能会得到极其奇怪的数字。
在结构体中使用联合技术通常是当您想要一种变体风格的结构时。它通常伴随着类型标识符,用于确定联合中要检查的项目。它也可以以相反的方式出现,例如在*NIX上的Xlib中,它是一个带有结构体的联合,所有结构体之间的第一个成员都相同,定义了哪个结构体具有所需的数据。
联合意味着它的成员可以作为其可能的值之一。 在下面的例子中,你可以看到每个成员的值。 但是这个联合可以是其他结构的成员,在那里只需要指定一个值-要么是浮点数,要么是整数,而不是两者都有。 希望这对你有所帮助。
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)