如何在 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 语言中使用 typedef
和 typedef 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
关键字是伪存储类说明符。从语法上讲,它与使用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
具有预期的指针类型,但其余标识符没有。
这可能是关于 typedef
和 C 中类型别名的所有内容的 99%。
【讨论】:
不应该是ulongptr q = p
,p 和 q 的类型完全相同吗?你写的方式,你可以有ulong *q = p
,这将与unsigned long *p
具有完全相同的类型
@Bhargav 你是对的,这是一个错字。 ulongptr *q = p
需要诊断;这是不相似的指针类型之间的转换,没有强制转换。
Godlike ASC 艺术技能 +2。以上是关于如何在 C 中使用 typedef 和 typedef 枚举?的主要内容,如果未能解决你的问题,请参考以下文章