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:
union is a member of a struct, then some other field
in the struct could be the discriminator.
union object is pointed to by a member of a struct,
then, again, some other field in the struct could be the
discriminator.
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:
ival_value() appears at the same level as
kind_value()