Search code examples
csyntaxstruct

What's the syntactically proper way to declare a C struct?


I've seen C structs declared several different ways before. Why is that and what, if anything, does each do different?

For example:

struct foo {
  short a;
  int b;
  float c;
};

typedef struct {
  short d;
  int e;
  float f;
} bar;

typedef struct _baz {
  short a;
  int b;
  float c;
} baz;

int main (int argc, char const *argv[])
{
  struct foo a;
  bar b;
  baz c;

  return 0;
}

Solution

  • Well, the obvious difference is demonstrated in your main:

    struct foo a;
    bar b;
    baz c;
    

    The first declaration is of an un-typedefed struct and needs the struct keyword to use. The second is of a typedefed anonymous struct, and so we use the typedef name. The third combines both the first and the second: your example uses baz (which is conveniently short) but could just as easily use struct _baz to the same effect.

    Update: larsmans' answer mentions a more common case where you have to use at least struct x { } to make a linked list. The second case wouldn't be possible here (unless you abandon sanity and use a void * instead) because the struct is anonymous, and the typedef doesn't happen until the struct is defined, giving you no way to make a (type-safe) pointer to the struct type itself. The first version works fine for this use, but the third is generally preferred in my experience. Give him some rep for that.

    A more subtle difference is in namespace placement. In C, struct tags are placed in a separate namespace from other names, but typedef names aren't. So the following is legal:

    struct test {
      // contents
    };
    
    struct test *test() {
      // contents
    }
    

    But the following is not, because it would be ambiguous what the name test is:

    typedef struct {
      // contents
    } test;
    
    test *test() {
      // contents
    }
    

    typedef makes the name shorter (always a plus), but it puts it in the same namespace as your variables and functions. Usually this isn't an issue, but it is a subtle difference beyond the simple shortening.