Learning that you can use unions in C for grouping things into namespaces
I've done a reasonable amount of programming in C and so I like to
think that I know it reasonably well. But still, every so often I
learn a new C trick and in the process learn that I didn't know C
quite as well as I thought. Today's trick is using C unions to group
struct
fields together, which I learned about through this LWN
article
(via).
Suppose that you have a struct
with a bunch of fields, and you
want to deal with some of them all together at once under a single
name; perhaps you want to conveniently copy them as a block through
struct assignment. However, you also want to keep simple field
access and for people using your struct
to not have to know that
these fields in particular are special (among other things, this
might keep the grouping from leaking into your API). The traditional
old school C approach to this is a sub-structure with #define
s on
top:
struct a { int field1; struct { int field_2; int field_3; } sub; }; #define field2 sub.field_2 #define field3 sub.field_3
(Update: corrected the code here to be right. It's been a while since I wrote C.)
One of the problems with this is the #define
s, which have very
much fallen out of favour as a way of renaming fields.
It turns out that modern C lets you do better than this by abusing
unions for namespace purposes. What you do is that you embed two
identical sub-struct
s inside an anonymous union, with the same
fields in each, and give one sub-struct
a name and keep the other
anonymous. The anonymous sub-struct inside the anonymous union lets
you access its fields without any additional levels of names. The
non-anonymous struct
lets you refer to the whole thing by name.
Like so:
struct a { int field1; union { struct { int field2; int field3; }; struct { int field2; int field3; } sub; }; };
You can access both a.field2
and a.sub
, and a.field2
is the
same as a.sub.field2
.
Naturally people create #define
macros to automate creating this
structure so that all fields stay in sync between the two struct
s
inside the union. Otherwise this "clever" setup is rather fragile.
(I think this may be a well known thing in the modern C community, but I'm out of touch with modern C for various reasons, especially perverse modern C. This is definitely perverse.)
Comments on this page:
|
|