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%。