Рассмотрим:
#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
}
}