简体   繁体   English

如何在 C 中使用 typedef 和 typedef 枚举?

[英]How do I use typedef and typedef enum in C?

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?如何在 C 中使用typedeftypedef enum What does this part of the code do?这部分代码的作用是什么?

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. typedef关键字是伪存储类说明符。 Syntactically, it is used in the same place where a storage class specifier like extern or static is used. 从语法上讲,它用于使用externstatic等存储类说明符的相同位置。 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 . 这意味着声明不会引入命名对象的存在,而是引入了类型别名的名称。

After the above declaration, the State identifier becomes an alias for the type enum state {DEAD,ALIVE} . 在上述声明之后, State标识符成为类型enum state {DEAD,ALIVE}的别名。 The declaration also provides that type itself. 声明还提供了类型本身。 However that isn't typedef doing it. 但是,这不是typedef Any declaration in which enum state {DEAD,ALIVE} appears as a type specifier introduces that type into the scope: enum state {DEAD,ALIVE}作为类型说明符出现的任何声明都会将该类型引入范围:

enum state {DEAD, ALIVE} stateVariable;

If enum state has previously been introduced the typedef has to be written like this: 如果先前已经引入了enum state则必须像这样编写typedef

typedef enum state State;

otherwise the enum is being redefined, which is an error. 否则enum被重新定义,这是一个错误。

Like other declarations (except function parameter declarations), the typedef declaration can have multiple declarators, separated by a comma. 与其他声明(函数参数声明除外)一样, typedef声明可以有多个声明符,用逗号分隔。 Moreover, they can be derived declarators, not only simple names: 而且,它们可以是派生的声明符,而不仅仅是简单的名称:

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. 这个typedef引入了两个类型名称ulongulongptr ,它们基于说明符限定符列表中给出的unsigned long类型。 ulong is just a straight alias for that type. ulong只是该类型的直接别名。 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. ulongptr被声明为指向unsigned long的指针,这要归功于*语法,该语法在这个角色中是一种类型构造运算符,故意模仿表达式中使用的指针解除引用的一元* In other words ulongptr is an alias for the "pointer to unsigned long " type. 换句话说, ulongptr是“指向unsigned long ”类型的别名。

Alias means that ulongptr is not a distinct type from unsigned long * . 别名意味着ulongptr 不是 unsigned long * 的独特类型 This is valid code, requiring no diagnostic: 这是有效的代码,无需诊断:

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

The variables q and p have exactly the same type. 变量qp具有完全相同的类型。

The aliasing of typedef isn't textual. typedef的别名不是文本的。 For instance if user_id_t is a typedef name for the type int , we may not simply do this: 例如,如果user_id_tint类型的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. 这是一个无效的类型说明符列表,将unsigned与typedef名称相结合。 The above can be done using the C preprocessor: 以上可以使用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. 从而在语法分析和转换之前将user_id_t宏扩展到标记int While this may seem like an advantage, it is a false one; 虽然这似乎是一种优势,但却是假的; avoid this in new programs. 在新程序中避免这种情况。

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: 这个声明没有声明whatyouthink是“指向int的类型”,因为宏扩展是:

 int * not, what, you, think;

The type specifier is int , and the declarators are *not , what , you and think . 类型说明符是int ,声明符是*notwhatyouthink So not has the expected pointer type, but the remaining identifiers do not. 所以not预期的指针类型,但其余的标识符没有。

And that's probably 99% of everything about typedef and type aliasing in C. 这可能是关于typedef和C语言类型别名的99%。

typedef defines a new data type. typedef定义了一种新的数据类型。 So you can have: 所以你可以:

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 ,事情有点不同 - 请考虑以下示例:

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

A typedef , is just an alias - typedef只是一个别名-

  • "typedef is a reserved keyword in the programming languages C and C++. It is used to create an additional name ( alias ) for another data type, but does not create a new type" ( Wiki ) “typedef 是编程语言 C 和 C++ 中的保留关键字。它用于为另一种数据类型创建附加名称别名),但不创建新类型”( Wiki

  • "the typedef declaration provides a way to declare an identifier as a type alias , to be used to replace a possibly complex type name" ( cppreference ) “typedef 声明提供了一种将标识符声明为类型别名的方法,用于替换可能复杂的类型名称”( cppreference

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM