Подтвердить что ты не робот

Как использовать 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? Что делает эта часть кода?

4b9b3361

Ответ 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.

Ответ 2

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
   }
}