8

Chris's Wiki :: blog/programming/CUnionsForNamespaces

 3 years ago
source link: https://utcc.utoronto.ca/~cks/space/blog/programming/CUnionsForNamespaces
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Learning that you can use unions in C for grouping things into namespaces

July 31, 2021

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 #defines on top:

struct a {
  int field1;
  struct sub {
    int field_2;
    int field_3;
  };
};

#define field2 sub.field_2
#define field2 sub.field_3

One of the problems with this is the #defines, 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-structs 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 structs 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.)


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK