Typedef和enum具有相同的名称?
在FreeImagePlus库中,在FreeImage.h
,有一个有趣的#define
似乎创建了一个typedef
和一个具有相同名称的enum
:
#define FI_ENUM(x) typedef int x; enum x
这由预处理器扩展为代码,如:
typedef int FREE_IMAGE_FILTER; enum FREE_IMAGE_FILTER { FILTER_BOX = 0, FILTER_BICUBIC = 1, [...]
这是做什么的? 拥有一个typedef
和一个同名的enum
是否合法? 并不是一个与int
兼容的enum
? 为什么FreeImage会这样做?
结构,联合和枚举的名称存在于它们自己的命名空间中。 这就是为什么你可以声明一个struct
/ union
/ enum
变量,其名称与实际的struct
/ union
/ enum
。
并且它不是完整enum
的名称(例如,对于enum X
我的意思是X
)必须与整数兼容,它是枚举中的名称。
引用C99 N1256草案 6.2.1“标识符范围”:
标识符可以表示对象; function; 标签或结构,联合或枚举的成员; 一个typedef名称; 标签名称; 宏名; 或宏参数。
这意味着:
typedef int id;
id
是一个标识符。
从6.2.3“标识符的名称空间”:
开始报价
如果在翻译单元中的任何点处可见多于一个特定标识符的声明,则句法上下文消除了引用不同实体的用法的歧义。 因此,各种标识符类别都有单独的名称空间,如下所示:
- 标签名称(通过标签声明和使用的语法消除歧义);
- 结构,联合和枚举的标记(通过遵循任何关键字struct,union或enum来消除歧义);
- 结构或工会的成员; 每个结构或联合为其成员都有一个单独的名称空间(通过。或 – >运算符用于访问成员的表达式的类型消除歧义);
- 所有其他标识符,称为普通标识符(在普通声明符中声明或作为枚举常量)。
结束语
所以在:
typedef int id; enum id {ID0};
- 第一个
id
是普通标识符 - 第二个是标签标识符
两者都可以和平共处。
另一方面,我们做不到这样的事情:
typedef int id; int id;
因为两者都是普通的标识符。