Рассмотрим:
#define MAXROW 20
#define MAXCOL 60
typedef State Grid[MAXROW+2] [MAXCOL+2]
typedef enum state {DEAD,ALIVE} State
Как использовать typedef и typedef enum в C? Что делает эта часть кода?
Рассмотрим:
#define MAXROW 20
#define MAXCOL 60
typedef State Grid[MAXROW+2] [MAXCOL+2]
typedef enum state {DEAD,ALIVE} State
Как использовать typedef и typedef enum в C? Что делает эта часть кода?
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.
typedef определяет новый тип данных. Таким образом, вы можете:
typedef char* my_string;
typedef struct{
int member1;
int member2;
}my_struct
Итак, теперь вы можете объявлять переменные с этими новыми типами данных
my_string s;
my_struct x;
s = "welcome";
x.member1 = 10;
Для Enum все немного отличается - рассмотрим следующие примеры:
enum Ranks {FIRST, SECOND};
int main()
{
int data = 20;
if (data == FIRST)
{
//do something
}
}
с использованием typedef enum создает псевдоним для типа:
typedef enum Ranks {FIRST, SECOND} Order;
int main()
{
Order data = (Order)20; // Must cast to defined type to prevent error
if (data == FIRST)
{
//do something
}
}