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; 

因为两者都是普通的标识符。