用法
typedef
是 C 语言的关键字之一,人尽皆知的用法就是“为一个类型取别名”,比如:
1 | typedef unsigned int size_t; |
或者:
1 | typedef struct Student student; |
还有:
1 | typedef struct Node* PtrtoNode; |
类似的例子有很多,但实际上“为一个类型取别名”这种说法是不严谨的。私认为typedef
关键字不仅仅是“取别名”,还要从语义的角度上去理解typedef
的行为。
比如:
1 | typedef int Arr[5]; |
从语义的角度而言,在上述代码中,Arr
是一种“新类型”(这里的新类型其实并不是真正意义上新类型),表示元素个数为 5 的int
数组,对应的a
是一个指向元素个数为 5 的int
数组的数组指针。对比类型一样、用基本类型声明的数组指针parr
,也可以看出使用typedef
带来的便利性。
实际上,熟悉 C++ 的同学,可能会发现typedef
和using
的功能有点类似。
类似的用法,还有定义函数指针的用法,如下:
1 | typedef void (*pfun)(int); |
上述代码中,定义了一个返回值为void
,参数为一个int
的函数指针类型pfun
。
陷阱
这里,还需要提一下typedef
和const
关键字一起使用时的陷阱——千万不要把typedef
和#define
的文本替换混为一谈。
比如:
1 |
|
在阅读下面的讨论之前,需要理解const typename *
和typename * const
的区别。
如果认为typedef
是文本替换,那么const pchar str
与const char *str
一致,对应语句*str = 'g';
就会出错,而str = s2;
就会正常执行(可以对比下面const char *
和const int
相关的代码)。但事实上,结果正好相反,编译器认为*str = 'g';
正确、str = s2;
错误,这说明,编译器并不认为str
是一个const char *
。
从语义的角度来理解,pchar
的类型是char
型的指针,在其前面加上一个const
,表示这个指针是一个常量,所以const pchar
的实际类型是char * const
,而不是const char *
,这点从后面的代码也可以对比出来。
最后需要说明的是,typedef
的用法是 C 的标准规定的,本文只是验证如何使用,而不是证明这是编译器的黑魔法😂。