A union behaves as if all its members are in the same location in memory, overlapping.
This is useful when you want to represent some kind of "generic" value, or a value that can be of any of a set of types. Because the fields overlap, you can only legally access a field if you know it's been previously initialized. Still, since C doesn't check this, and many compilers emit code that allow it, it is a common trick to do ... interesting type conversions, such as:
union {
int integer;
float real;
} convert;
convert.real = 3.14;
printf("The float %f interpreted as an integer is %08x", convert.real, convert.integer);
For the more well-formed usage, where you keep track of what was last stored in the union, it could look for instance like this:
typedef enum { INTEGER = 0, REAL, BOOLEAN, STRING } ValueType;
typedef struct {
ValueType type;
union {
int integer;
float real;
char boolean;
char *string;
} x;
} Value;
Here, note that the union is actually a field in the surrounding structure, Value
. Access could look like this:
void value_set_integer(Value *value, int x)
{
value->type = INTEGER;
value->x.integer = x;
}
This records that the current contents of the union is an integer, and stores the given value. A function to e.g. print a Value
can inspect the type
member, and do the right thing:
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 ... */
}
}
There is no equivalent in Java. C++, being sort of almost a super-set of C, has the same functionality. It even "one-ups" C's implementation, and allows anonymous unions. In C++, the above could have written without naming the inner union (x
), which would make the code quite a lot shorter.