联合的行为就好像它的所有成员都在内存中的同一位置,重叠。
当您想要表示某种“通用”值或可以是任何一组类型的值时,这很有用。由于字段重叠,因此只有在您知道该字段之前已初始化的情况下才能合法访问该字段。尽管如此,由于 C 不检查这一点,并且许多编译器发出允许它的代码,所以这是一个常见的技巧......有趣的类型转换,例如:
union {
int integer;
float real;
} convert;
convert.real = 3.14;
printf("The float %f interpreted as an integer is %08x", convert.real, convert.integer);
对于格式更正确的用法,您可以跟踪最后存储在联合中的内容,它可能看起来像这样:
typedef enum { INTEGER = 0, REAL, BOOLEAN, STRING } ValueType;
typedef struct {
ValueType type;
union {
int integer;
float real;
char boolean;
char *string;
} x;
} Value;
这里,注意联合实际上是周围结构中的一个字段,Value。访问可能如下所示:
void value_set_integer(Value *value, int x)
{
value->type = INTEGER;
value->x.integer = x;
}
这记录了联合的当前内容是一个整数,并存储给定的值。一个函数,例如打印Value 可以检查type 成员,并做正确的事:
void value_print(const Value *value)
{
switch(value->type)
{
case INTEGER:
printf("%d\n", value->x.integer);
break;
case REAL:
printf("%g\n", value->x.real);
break;
/* ... and so on ... */
}
}
Java 中没有等价物。 C++ 几乎是 C 的超集,具有相同的功能。它甚至“one-ups” C 的实现,并允许anonymous unions。在 C++ 中,上面的代码可以不用命名内部联合 (x) 来编写,这会使代码更短。