如何在C中使用typedef和typedef enum?

时间:2013-12-06 14:44:48

标签: c typedef

考虑:

#define MAXROW 20
#define MAXCOL 60
typedef State Grid[MAXROW+2] [MAXCOL+2]
typedef enum state {DEAD,ALIVE} State

如何在C中使用typedeftypedef enum?这段代码的作用是什么?

3 个答案:

答案 0 :(得分:94)

typedef enum state {DEAD,ALIVE} State;
|     | |                     | |   |^ terminating semicolon, required! 
|     | |   type specifier    | |   |
|     | |                     | ^^^^^  declarator (simple name)
|     | |                     |    
|     | ^^^^^^^^^^^^^^^^^^^^^^^  
|     |
^^^^^^^-- storage class specifier (in this case typedef)

typedef关键字是伪存储类说明符。从语法上讲,它用于使用externstatic等存储类说明符的相同位置。它与存储没有任何关系。这意味着声明不会引入命名对象的存在,而是引入了类型别名的名称。

在上述声明之后,State标识符成为类型enum state {DEAD,ALIVE}的别名。声明还提供了类型本身。然而,这不是typedef这样做的。 enum state {DEAD,ALIVE}作为类型说明符出现的任何声明会将该类型引入范围:

enum state {DEAD, ALIVE} stateVariable;

如果之前已经引入了enum statetypedef必须像这样写:

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类型引入了两个类型名称ulongptrunsigned longulong只是该类型的直接别名。由于ulongptr语法,unsigned long被声明为指向*的指针,在此角色中是一种类型构造运算符,故意模仿指针的一元*表达式中使用的解除引用。换句话说,ulongptr是“指向unsigned long”类型的指针的别名。

别名意味着ulongptr 不是来自unsigned long *的独特类型。这是有效的代码,无需诊断:

unsigned long *p = 0;
ulongptr q = p;

变量qp具有完全相同的类型。

typedef的别名不是文字的。例如,如果user_id_ttypedef类型的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;

此声明未声明whatyouthink为“指向int的类型”,因为宏扩展为:

 int * not, what, you, think;

类型说明符为int,声明符为*notwhatyouthink。因此not具有预期的指针类型,但其余标识符不具有。

这可能是typedef所有内容的99%,并在C中输入别名。

答案 1 :(得分:23)

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

答案 2 :(得分:1)

只是一个补充:

6.7.8类型定义

  

typedef声明不会引入新的类型,只是这样指定的类型的同义词。

open-std.org ISO/IEC 9899:2017

同意typedef在C中创建新数据类型的人们应该在free()函数中拖曳,并将对其名称的所有引用都设置为NULL