Ответ 1
typedef enum state {DEAD,ALIVE} State;
| | | | | |^ terminating semicolon, required!
| | | type specifier | | |
| | | | ^^^^^ declarator (simple name)
| | | |
| | ^^^^^^^^^^^^^^^^^^^^^^^
| |
^^^^^^^-- storage class specifier (in this case typedef)
Ключевое слово typedef
- спецификатор класса псевдо-хранения. Синтаксически он используется в том же месте, где используется спецификатор класса хранения, например extern
или static
. Это не имеет ничего общего с хранилищем. Это означает, что в декларации не указано существование названных объектов, но вместо этого они вводят имена, которые являются псевдонимами типа.
После указанного объявления идентификатор State
становится псевдонимом для типа enum state {DEAD,ALIVE}
. В декларации также указан этот тип. Однако это не значит typedef
. Любое объявление, в котором enum state {DEAD,ALIVE}
появляется как спецификатор типа, вводит этот тип в область видимости:
enum state {DEAD, ALIVE} stateVariable;
Если ранее было введено enum state
, typedef
должно быть написано так:
typedef enum state State;
в противном случае enum
переопределяется, что является ошибкой.
Как и другие объявления (кроме объявлений параметров параметра), объявление typedef
может иметь несколько деклараторов, разделенных запятой. Более того, они могут быть производными деклараторами, а не только простыми именами:
typedef unsigned long ulong, *ulongptr;
| | | | | 1 | | 2 |
| | | | | | ^^^^^^^^^--- "pointer to" declarator
| | | | ^^^^^^------------- simple declarator
| | ^^^^^^^^^^^^^-------------------- specifier-qualifier list
^^^^^^^---------------------------------- storage class specifier
Этот typedef
вводит два типа имен ulong
и ulongptr
на основе типа unsigned long
, указанного в списке спецификаторов-спецификаторов. ulong
- просто прямой псевдоним для этого типа. ulongptr
объявляется как указатель на unsigned long
, благодаря синтаксису *
, который в этой роли является своего рода оператором построения типа, который намеренно имитирует унарный *
для разыменования указателя, используемого в выражениях. Другими словами, ulongptr
является псевдонимом для типа "указатель на unsigned long
".
Псевдоним означает, что ulongptr
не является отдельным типом из unsigned long *
. Это действительный код, не требующий диагностики:
unsigned long *p = 0;
ulongptr q = p;
Переменные q
и p
имеют точно такой же тип.
Сглаживание typedef
не является текстовым. Например, если user_id_t
является typedef
именем для типа int
, мы можем не просто сделать это:
unsigned user_id_t uid; // error! programmer hoped for "unsigned int uid".
Это недопустимый список спецификаторов типов, объединяющий unsigned
с именем typedef. Вышеприведенное может быть выполнено с использованием препроцессора C:
#define user_id_t int
unsigned user_id_t uid;
в результате чего user_id_t
выполняется макрообмена до токена int
до синтаксического анализа и перевода. Хотя это может показаться преимуществом, оно ложное; избегайте этого в новых программах.
Среди недостатков, которые он плохо работает для производных типов:
#define silly_macro int *
silly_macro not, what, you, think;
Это объявление не объявляет what
, you
и think
как тип "указатель на int", потому что макроразложение:
int * not, what, you, think;
Спецификатор типа int
, а деклараторы *not
, what
, you
и think
. Итак, not
имеет ожидаемый тип указателя, но остальные идентификаторы этого не делают.
И это, вероятно, 99% всего о typedef
и тип aliasing в C.