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

Posted

技术标签:

【中文标题】如何在 C 中使用 typedef 和 typedef 枚举?【英文标题】:How do I use typedef and typedef enum in C? 【发布时间】:2013-12-23 23:17:39 【问题描述】:

考虑:

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

如何在 C 语言中使用 typedeftypedef enum?这部分代码是做什么的?

【问题讨论】:

欢迎来到 SO!这个问题有点太基本了,很可能已经在 SO 上问过了。你用什么材料来学习C?你应该找到一个更好的材料来回答这个问题,否则你会被问题困住太多。在 Google 和 SO 上寻找最好的 C 教程。 其实我知道基本的 C 但那个网格语句是我不清楚的 【参考方案1】:

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
   

【讨论】:

在第二个例子中,20和first或second如何比较? 枚举是整数类型;枚举中的第一个值为 0(除非另有说明),第二个是第一个值 +1(在这种情况下为 0+1),依此类推。当您声明一个 enum_data_type 类型的变量时,您只能为其分配存在于 enum 中的值......编译器会进行验证。 所以在第二个例子中,如果(data==FIRST)是假的,如果我分配 int data=0 会是真的吗? typedef 没有定义新的数据类型;它定义了现有数据类型的标识符。 typedef 与枚举一起使用不会影响枚举的属性。你的第二对例子:首先它是一个红鲱鱼,在第一个例子中你可以写enum Ranks data = 20;而不是int data = 20;。但在这两种情况下,都允许将20 分配给枚举类型的变量,这不是错误。【参考方案2】:
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 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 引入了两个类型名称ulongulongptr,基于在说明符-限定符列表中给出的unsigned long 类型。 ulong 只是该类型的直接别名。 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 和 C 中类型别名的所有内容的 99%。

【讨论】:

不应该是ulongptr q = p,p 和 q 的类型完全相同吗?你写的方式,你可以有ulong *q = p,这将与unsigned long *p具有完全相同的类型 @Bhargav 你是对的,这是一个错字。 ulongptr *q = p 需要诊断;这是不相似的指针类型之间的转换,没有强制转换。 Godlike ASC 艺术技能 +2。

以上是关于如何在 C 中使用 typedef 和 typedef 枚举?的主要内容,如果未能解决你的问题,请参考以下文章

C - #include 和多个 typedef

C++ typedef typename 作用

typedef见解即如何定义一个数组指针

C ++检查是不是定义了typedef [重复]

c语言byte类型 typedef unsigned char byte[20]; 如何初始化

C的typedef的说明