I have some code that is very similar to the following
struct T {
union {
unsigned int x;
struct {
unsigned short xhigh;
unsigned short xlow;
};
} x;
/* ...repeated a handful of times for different variables in T... */
};
This does exactly what you'd expect: It allows me to declare a variable of type struct T
and access either t.x.x
or t.x.xhigh
or t.x.xlow
. So far so good.
However, I would really like it if I could do just t.x
in the common case of wanting to access the value of the union as an unsigned int
quantity, but retain the ability to access the high- and low-order portions independently without resorting to bit masking and shifting, and without invoking undefined behavior.
Is that possible in C?
If it is possible, then what is the C syntax for the declaration?
When I try the naiive approach of simply accessing t.x
instead of t.x.x
, I get warning messages like (this particular one is from a printf()
call):
cc -ansi -o test -Wall test.c
test.c: In function ‘my_function’:
test.c:13:2: warning: format ‘%X’ expects argument of type ‘unsigned int’, but argument 2 has type ‘const union <anonymous>’ [-Wformat]
Using -std=c11
instead of -ansi
yields the same warning.
Anonymous unions are a thing, if you can use anonymous structs (they are both C11 features or compiler extensions).
Just as you've used a struct
with no name to inject its members into the union's namespace, so you can also use a union
with no name to inject its members into the enclosing namespace. Like so:
struct T {
union {
unsigned int x;
struct {
unsigned short xhigh;
unsigned short xlow;
};
}; /* <-- no name here */
/* ...repeated a handful of times for different variables in T... */
};
You just have to make sure that none of the injected names clash with other injected names or regular names that are there, otherwise it won't compile.
One concern though: you seem to be relying on the "fact" that unsigned short
is half the size of unsigned int
, and that these types are big-endian. But if that's what happens on your system, then that's fine. If not, I suggest you rethink the structure.