typedef in C

I regularly coach advanced C to the great engineers at Tandberg in Oslo. One of the topics we've discussed is typedef style. For example
  • not using typedefs (Linux kernel style) like this
struct wibble;

void wibble_this(struct wibble *);
void wibble_that(struct wibble *);
  • or with typedefs, like this
struct wibble;

typedef struct wibble wibble;

void wibble_this(wibble *);
void wibble_that(wibble *);
This matters because typedefs are not idempotent in C, which is to say you can't write this
typedef struct wibble wibble;
...
typedef struct wibble wibble; // non-conforming duplicate
A C file has its #includes and these #includes will have their own #includes, ad infinitum. It can be tricky knowing whether a type has already been typedef'd or not, and hence whether the C file has to declare its own typedef or not (for example, when forward declaring the type). However, there is a style that neatly avoids this problem
  • in header files don't typedef
// wibble.h
struct wibble;

void wibble_this(struct wibble *);
void wibble_that(struct wibble *);
  • in source files do typedef
// use.c
#include "wibble.h"

typedef struct wibble wibble;

void eg1(wibble * w)
{
    ...
}

void eg2(void)
{
    wibble * w = ...
    ...
}
This is somewhat similar to the C++ rule that header files always use explicit :: qualification. My friend Kevlin Henney commented that the idea is also resembles using typedef's in the private section of a C++ class which is a nice observation. I haven't tried this on a large codebase. At the moment it's just an idea. Caveat emptor.

2 comments:

  1. Just a quick question: What are the advantages of typedef'ing structs the way you propose?

    ReplyDelete
  2. Simply to avoid duplication in the source file. When something _always_ appears it's often a sign of a missing abstraction. If we typedef it away it allows us to raise the level of abstraction ever so slightly. It can also be argued that the struct prefix on the declarations is somewhat similar to Hungarian notation.

    ReplyDelete