Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the differences between these two typedef styles in C?

I'm curious what the difference here is when typedefing an enum or struct. Is there any difference semantically between these two blocks?

This:

typedef enum { first, second, third } SomeEnum;

and this:

enum SomeEnum { first, second, third };
typedef enum SomeEnum SomeEnum;

Same deal for structs. I've seen both in use, and they both seem to do the same thing in C or Objective-C. Is there a real difference or is it just a preference for which style you can use?

like image 755
Kevlar Avatar asked Jul 06 '10 21:07

Kevlar


1 Answers

The difference is that the second approach declares a type named enum SomeEnum and also declares a typedef-name SomeEnum - an alias for that type. It can actually be combined into the equivalent one-liner

typedef enum SomeEnum { first, second, third } SomeEnum;

which makes it rather obvious that the only difference between the two approaches is whether there's a name after the enum keyword. With the second approach, you can declare object of that enum type by using either SomeEnum e or enum SomeEnum e, whichever you prefer.

The first approach only declares the typedef-name SomeEnum for an originally anonymous enum type, meaning that you are limited to SomeEnum e declarations.

So, as long as you only use the typedef-name SomeEnum in your declarations, there will be no difference between the two. However, in some cases you might have to use the full original name of the type enum SomeEnum. In the first approach that name is not available, so you'll be out of luck.

For example, if after the above declaration you also declare a variable named SomeEnum in some nested scope

int SomeEnum;

the name of the variable will hide the typedef-name of the enum, thus making this declaration illegal

SomeEnum e; /* ERROR: `SomeEnum` is not a type */

However, if you used the second approach when declaring your enum, you can work around this problem by using the full type name

enum SomeEnum e; /* OK */

This would not be possible if you used the first approach when declaring your enum type.

When used with structs, the name after the struct is a must when you need a self-referencing type (a type that contains a pointer to the same type), like

typedef struct SomeStruct {
  struct SomeStruct *next;
} SomeStruct;

Finally, in the second approach the typedef name is totally optional. You can simply declare

enum SomeEnum { first, second, third };

and just use enum SomeEnum every time you need to refer to this type.

like image 109
AnT Avatar answered Oct 05 '22 17:10

AnT