Unix APIs are where I first saw C #define used to rename struct fields

In my entry on learning that you can use C unions for grouping struct fields into namespaces , I mentioned that the traditional version of this was done with #define to create convenient short names for fields that were actually hidden deeper in a struct than they appeared. I didn't come up with this idea on my own; instead, I'm pretty sure that where I first saw this was in Unix APIs. More exactly, in the actual implementation of Unix APIs, as visible in C header files. Most often, I think this was done because of unions in the struct, which at the time had to be named.

A typical example that I can find is in the 4.2 BSD arpa/tftp.h header:

struct tftphdr {
  short th_opcode;     /* packet type */
  union {
    short tu_block;    /* block # */
    short tu_code;     /* error code */
    char  tu_stuff[1]; /* request packet stuff */
  } th_u;
  char th_data[1];     /* data or error string */
};

#define th_block  th_u.tu_block
#define th_code   th_u.tu_code
#define th_stuff  th_u.tu_stuff

Here various #define s are being used to give short names to things that are actually inside a union. Today we could do this directly with an anonymous union, but those only officially appeared in C11 after being a GNU gcc extension.

(Another example is in the 4.2 BSD wait.h , which despite its position in the tree here was also in /usr/include ; see MAKEDIRS . Another generally more internal use is in inode.h .)

This approach would have serious problems with th_block or other #defined d fields if they were also used in one of your own struct s for some other purpose. But in the very old days of C, struct fields had to be globally unique across your entire program, so it was common to give them a relatively unique name and you already knew you had problems if you reused a field name from what the manpage said was a struct that was part of a library API.

(I haven't looked at how the early C compilers implemented struct fields, but I suspect that the V7 C compiler just put all struct field names into a global table with their type and offset. This seems a very V7 shortcut.)