## Discriminating Unions

One possible source of bugs in C is referring to the wrong field of a `union`.

Usually, there is some way of knowing the field of the `union` that is currently valid. This is the discriminator for the union. For debugging purposes, whenever we refer to some field of the union, we should evaluate the discriminator to see if the field is the currently valid field of the `union`.

There are many possible discriminators:

• If the `union` is a member of a `struct`, then some other field in the `struct` could be the discriminator.
• If the `union` object is pointed to by a member of a `struct`, then, again, some other field in the `struct` could be the discriminator.
• The discriminator does not have to be a field; it could be function of multiple fields of the `struct`.

The first case (the `union` being the member of the `struct`) is fairly common; we use the following accessor idiom to access the fields of the `union` in a controlled fashion.

``````
enum value_kind {
ivalue_kind,
dvalue_kind,
};

struct value {
enum value_kind	v_kind;
union {
int		v_ival;
double	v_dval;
} v_u;
};

#define deref_value(_x)		(_x)
#define x_kind_value(_x)	(deref_value(_x)->v_kind)
#define x_ival_value(_x) \
( deref_value( assert(x_kind_value(_x) == ivalue_kind),
(_x))->v_u.v_ival )
#define x_dval_value(_x) \
( deref_value( assert(x_kind_value(_x) == dvalue_kind),
(_x))->v_u.v_dval )

#define kind_value(_x)		((void)0, x_kind_value(_x))
#define ival_value(_x)		((void)0, x_ival_value(_x))
#define dval_value(_x)		((void)0, x_dval_value(_x))
``````

Note how the accessor macros work:

• Before accessing a field of the union, the macros check to see if it is the valid field.
• The fact that they are fields of a union is hidden in the accessor macro; e.g. `ival_value()` appears at the same level as `kind_value()`

Next Prev Main Top Feedback