Разница в том, что второй подход объявляет тип с именем enum SomeEnum
, а также объявляет typedef-name SomeEnum
- псевдоним для этого типа. Это на самом деле может быть объединено в эквивалентный однострочник
typedef enum SomeEnum { first, second, third } SomeEnum;
, что делает его довольно очевидно, что единственное различие между этими двумя подходами есть ли это имя после enum
ключевого слова. При втором подходе вы можете объявить объект этого типа перечисления, используя SomeEnum e
или enum SomeEnum e
, в зависимости от того, что вы предпочитаете.
Первый подход только объявляет typedef-name SomeEnum
для анонимного типа перечисления, что означает, что вы ограничены объявлениями SomeEnum e
.
Итак, до тех пор, пока вы используете только имя typedef SomeEnum
в своих объявлениях, между ними не будет разницы. Однако в некоторых случаях вам, возможно, придется использовать полное оригинальное имя типа enum SomeEnum
. В первом подходе это имя недоступно, поэтому вам не повезет.
Например, если после указанной декларации вы также объявить переменную с именем SomeEnum
в некоторой вложенной сферы
int SomeEnum;
имя переменной будет скрыть имя-ЬурейеЕ из перечисления, таким образом, делая это заявление незаконным
SomeEnum e; /* ERROR: `SomeEnum` is not a type */
Однако, если вы использовали второй подход при объявлении вашего перечисления, вы можете обойти эту проблему, используя полное имя типа
enum SomeEnum e; /* OK */
Это было бы невозможно, если вы использовали первый подход при объявлении вашего типа перечисления.
При использовании структур, имя после struct
является обязательным, если вам нужен тип автореферентного (тип, который содержит указатель тот же тип), как
typedef struct SomeStruct {
struct SomeStruct *next;
} SomeStruct;
Наконец, в второй подход - имя typedef полностью необязательно. Вы можете просто объявить
enum SomeEnum { first, second, third };
и просто использовать enum SomeEnum
каждый раз, когда вам нужно обратиться к этому типу.