How do I use typedef and typedef enum in C?

c, typedef

Solution

typedef enum state {DEAD,ALIVE} State;
|     | |                     | |   |^ terminating semicolon, required! 
|     | |   type specifier    | |   |
|     | |                     | ^^^^^  declarator (simple name)
|     | |                     |    
|     | ^^^^^^^^^^^^^^^^^^^^^^^  
|     |
^^^^^^^-- storage class specifier (in this case typedef)

The `typedef` keyword is a pseudo-storage-class specifier. Syntactically, it is used in the same place where a storage class specifier like `extern` or `static` is used. It doesn't have anything to do with storage. It means that the declaration doesn't introduce the existence of named objects, but rather, it introduces names which are type aliases.

After the above declaration, the `State` identifier becomes an alias for the type `enum state {DEAD,ALIVE}`. The declaration also provides that type itself. However that isn't `typedef` doing it. Any declaration in which `enum state {DEAD,ALIVE}` appears as a type specifier introduces that type into the scope:

enum state {DEAD, ALIVE} stateVariable;

If `enum state` has previously been introduced the `typedef` has to be written like this:

typedef enum state State;

otherwise the `enum` is being redefined, which is an error.

Like other declarations (except function parameter declarations), the `typedef` declaration can have multiple declarators, separated by a comma. Moreover, they can be derived declarators, not only simple names:

typedef unsigned long ulong, *ulongptr;
|     | |           | |  1 | |   2   |
|     | |           | |    | ^^^^^^^^^--- "pointer to" declarator
|     | |           | ^^^^^^------------- simple declarator
|     | ^^^^^^^^^^^^^-------------------- specifier-qualifier list
^^^^^^^---------------------------------- storage class specifier

This `typedef` introduces two type names `ulong` and `ulongptr`, based on the `unsigned long` type given in the specifier-qualifier list. `ulong` is just a straight alias for that type. `ulongptr` is declared as a pointer to `unsigned long`, thanks to the `*` syntax, which in this role is a kind of type construction operator which deliberately mimics the unary `*` for pointer dereferencing used in expressions. In other words `ulongptr` is an alias for the "pointer to `unsigned long`" type.

Alias means that `ulongptr` is not a distinct type from `unsigned long *`. This is valid code, requiring no diagnostic:

unsigned long *p = 0;
ulongptr q = p;

The variables `q` and `p` have exactly the same type.

The aliasing of `typedef` isn't textual. For instance if `user_id_t` is a `typedef` name for the type `int`, we may not simply do this:

unsigned user_id_t uid;  // error! programmer hoped for "unsigned int uid". 

This is an invalid type specifier list, combining `unsigned` with a typedef name. The above can be done using the C preprocessor:

#define user_id_t int
unsigned user_id_t uid;

whereby `user_id_t` is macro-expanded to the token `int` prior to syntax analysis and translation. While this may seem like an advantage, it is a false one; avoid this in new programs.

Among the disadvantages that it doesn't work well for derived types:

 #define silly_macro int *

 silly_macro not, what, you, think;

This declaration doesn't declare `what`, `you` and `think` as being of type "pointer to int" because the macro-expansion is:

 int * not, what, you, think;

The type specifier is `int`, and the declarators are `*not`, `what`, `you` and `think`. So `not` has the expected pointer type, but the remaining identifiers do not.

And that's probably 99% of everything about `typedef` and type aliasing in C.

Problem

Consider: ``` #define MAXROW 20 #define MAXCOL 60 typedef State Grid[MAXROW+2] [MAXCOL+2] typedef enum state {DEAD,ALIVE} State ``` How do I use `typedef` and `typedef enum` in C? What does this part of the code do?

Original source