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

时间:2021-09-18 20:56:29

Consider:

考虑:

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

How do I use typedef and typedef enum in C? What does this part of the code do?

如何在C中使用typedef和typedef enum?这部分代码有什么作用?

2 个解决方案

#1


74  

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

The typedef keyword is a pseudo-storage-class specifier. Syntactically, it is used in the same place where a storage class specifier like extern or static is used. It doesn't have anything to do with storage. It means that the declaration doesn't introduce the existence of named objects, but rather, it introduces names which are type aliases.

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

After the above declaration, the State identifier becomes an alias for the type enum state {DEAD,ALIVE}. The declaration also provides that type itself. However that isn't typedef doing it. Any declaration in which enum state {DEAD,ALIVE} appears as a type specifier introduces that type into the scope:

在上述声明之后,状态标识符成为类型枚举状态{DEAD,ALIVE}的别名。声明还提供了类型本身。但是,这不是typedef。枚举状态{DEAD,ALIVE}作为类型说明符出现的任何声明都会将该类型引入范围:

enum state {DEAD, ALIVE} stateVariable;

If enum state has previously been introduced the typedef has to be written like this:

如果先前已经引入了枚举状态,则必须按如下方式编写typedef:

typedef enum state State;

otherwise the enum is being redefined, which is an error.

否则枚举被重新定义,这是一个错误。

Like other declarations (except function parameter declarations), the typedef declaration can have multiple declarators, separated by a comma. Moreover, they can be derived declarators, not only simple names:

与其他声明(函数参数声明除外)一样,typedef声明可以有多个声明符,用逗号分隔。而且,它们可以是派生的声明符,而不仅仅是简单的名称:

typedef unsigned long ulong, *ulongptr;
|     | |           | |  1 | |   2   |
|     | |           | |    | ^^^^^^^^^--- "pointer to" declarator
|     | |           | ^^^^^^------------- simple declarator
|     | ^^^^^^^^^^^^^-------------------- specifier-qualifier list
^^^^^^^---------------------------------- storage class specifier

This typedef introduces two type names ulong and ulongptr, based on the unsigned long type given in the specifier-qualifier list. ulong is just a straight alias for that type. ulongptr is declared as a pointer to unsigned long, thanks to the * syntax, which in this role is a kind of type construction operator which deliberately mimics the unary * for pointer dereferencing used in expressions. In other words ulongptr is an alias for the "pointer to unsigned long" type.

这个typedef引入了两个类型名称ulong和ulongptr,它们基于说明符限定符列表中给出的unsigned long类型。 ulong只是该类型的直接别名。 ulongptr被声明为指向unsigned long的指针,这要归功于*语法,该语法在这个角色中是一种类型构造运算符,故意模仿表达式中使用的指针解引用的一元*。换句话说,ulongptr是“指向unsigned long”类型的别名。

Alias means that ulongptr is not a distinct type from unsigned long *. This is valid code, requiring no diagnostic:

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

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

The variables q and p have exactly the same type.

变量q和p具有完全相同的类型。

The aliasing of typedef isn't textual. For instance if user_id_t is a typedef name for the type int, we may not simply do this:

typedef的别名不是文本的。例如,如果user_id_t是int类型的typedef名称,我们可能不会简单地这样做:

unsigned user_id_t uid;  // error! programmer hoped for "unsigned int uid". 

This is an invalid type specifier list, combining unsigned with a typedef name. The above can be done using the C preprocessor:

这是一个无效的类型说明符列表,将unsigned与typedef名称组合在一起。以上可以使用C预处理器完成:

#define user_id_t int
unsigned user_id_t uid;

whereby user_id_t is macro-expanded to the token int prior to syntax analysis and translation. While this may seem like an advantage, it is a false one; avoid this in new programs.

在语法分析和翻译之前,user_id_t被宏扩展到标记int。虽然这似乎是一种优势,但却是假的;在新程序中避免这种情况。

Among the disadvantages that it doesn't work well for derived types:

其中的缺点是它不适用于派生类型:

 #define silly_macro int *

 silly_macro not, what, you, think;

This declaration doesn't declare what, you and think as being of type "pointer to int" because the macro-expansion is:

这个声明没有声明什么,你并认为是“指向int的类型”,因为宏扩展是:

 int * not, what, you, think;

The type specifier is int, and the declarators are *not, what, you and think. So not has the expected pointer type, but the remaining identifiers do not.

类型说明符是int,声明符是* not,what,you和think。所以没有预期的指针类型,但其余的标识符没有。

And that's probably 99% of everything about typedef and type aliasing in C.

这可能是关于typedef和C语言类型别名的99%。

#2


19  

typedef defines a new data type. So you can have:

typedef定义了一种新的数据类型。所以你可以:

typedef char* my_string;
typedef struct{
  int member1;
  int member2;
} my_struct;

So now you can declare variables with these new data types

所以现在您可以使用这些新数据类型声明变量

my_string s;
my_struct x;

s = "welcome";
x.member1 = 10;

For enum, things are a bit different - consider the following examples:

对于枚举,事情有点不同 - 请考虑以下示例:

enum Ranks {FIRST, SECOND};
int main()
{
   int data = 20;
   if (data == FIRST)
   {
      //do something
   }
}

using typedef enum creates an alias for a type:

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

#1


74  

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

The typedef keyword is a pseudo-storage-class specifier. Syntactically, it is used in the same place where a storage class specifier like extern or static is used. It doesn't have anything to do with storage. It means that the declaration doesn't introduce the existence of named objects, but rather, it introduces names which are type aliases.

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

After the above declaration, the State identifier becomes an alias for the type enum state {DEAD,ALIVE}. The declaration also provides that type itself. However that isn't typedef doing it. Any declaration in which enum state {DEAD,ALIVE} appears as a type specifier introduces that type into the scope:

在上述声明之后,状态标识符成为类型枚举状态{DEAD,ALIVE}的别名。声明还提供了类型本身。但是,这不是typedef。枚举状态{DEAD,ALIVE}作为类型说明符出现的任何声明都会将该类型引入范围:

enum state {DEAD, ALIVE} stateVariable;

If enum state has previously been introduced the typedef has to be written like this:

如果先前已经引入了枚举状态,则必须按如下方式编写typedef:

typedef enum state State;

otherwise the enum is being redefined, which is an error.

否则枚举被重新定义,这是一个错误。

Like other declarations (except function parameter declarations), the typedef declaration can have multiple declarators, separated by a comma. Moreover, they can be derived declarators, not only simple names:

与其他声明(函数参数声明除外)一样,typedef声明可以有多个声明符,用逗号分隔。而且,它们可以是派生的声明符,而不仅仅是简单的名称:

typedef unsigned long ulong, *ulongptr;
|     | |           | |  1 | |   2   |
|     | |           | |    | ^^^^^^^^^--- "pointer to" declarator
|     | |           | ^^^^^^------------- simple declarator
|     | ^^^^^^^^^^^^^-------------------- specifier-qualifier list
^^^^^^^---------------------------------- storage class specifier

This typedef introduces two type names ulong and ulongptr, based on the unsigned long type given in the specifier-qualifier list. ulong is just a straight alias for that type. ulongptr is declared as a pointer to unsigned long, thanks to the * syntax, which in this role is a kind of type construction operator which deliberately mimics the unary * for pointer dereferencing used in expressions. In other words ulongptr is an alias for the "pointer to unsigned long" type.

这个typedef引入了两个类型名称ulong和ulongptr,它们基于说明符限定符列表中给出的unsigned long类型。 ulong只是该类型的直接别名。 ulongptr被声明为指向unsigned long的指针,这要归功于*语法,该语法在这个角色中是一种类型构造运算符,故意模仿表达式中使用的指针解引用的一元*。换句话说,ulongptr是“指向unsigned long”类型的别名。

Alias means that ulongptr is not a distinct type from unsigned long *. This is valid code, requiring no diagnostic:

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

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

The variables q and p have exactly the same type.

变量q和p具有完全相同的类型。

The aliasing of typedef isn't textual. For instance if user_id_t is a typedef name for the type int, we may not simply do this:

typedef的别名不是文本的。例如,如果user_id_t是int类型的typedef名称,我们可能不会简单地这样做:

unsigned user_id_t uid;  // error! programmer hoped for "unsigned int uid". 

This is an invalid type specifier list, combining unsigned with a typedef name. The above can be done using the C preprocessor:

这是一个无效的类型说明符列表,将unsigned与typedef名称组合在一起。以上可以使用C预处理器完成:

#define user_id_t int
unsigned user_id_t uid;

whereby user_id_t is macro-expanded to the token int prior to syntax analysis and translation. While this may seem like an advantage, it is a false one; avoid this in new programs.

在语法分析和翻译之前,user_id_t被宏扩展到标记int。虽然这似乎是一种优势,但却是假的;在新程序中避免这种情况。

Among the disadvantages that it doesn't work well for derived types:

其中的缺点是它不适用于派生类型:

 #define silly_macro int *

 silly_macro not, what, you, think;

This declaration doesn't declare what, you and think as being of type "pointer to int" because the macro-expansion is:

这个声明没有声明什么,你并认为是“指向int的类型”,因为宏扩展是:

 int * not, what, you, think;

The type specifier is int, and the declarators are *not, what, you and think. So not has the expected pointer type, but the remaining identifiers do not.

类型说明符是int,声明符是* not,what,you和think。所以没有预期的指针类型,但其余的标识符没有。

And that's probably 99% of everything about typedef and type aliasing in C.

这可能是关于typedef和C语言类型别名的99%。

#2


19  

typedef defines a new data type. So you can have:

typedef定义了一种新的数据类型。所以你可以:

typedef char* my_string;
typedef struct{
  int member1;
  int member2;
} my_struct;

So now you can declare variables with these new data types

所以现在您可以使用这些新数据类型声明变量

my_string s;
my_struct x;

s = "welcome";
x.member1 = 10;

For enum, things are a bit different - consider the following examples:

对于枚举,事情有点不同 - 请考虑以下示例:

enum Ranks {FIRST, SECOND};
int main()
{
   int data = 20;
   if (data == FIRST)
   {
      //do something
   }
}

using typedef enum creates an alias for a type:

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