6

在库FreeImagePlusFreeImage.h,有一个有趣#define的东西似乎创建了 atypedef和 anenum同名:

#define FI_ENUM(x)      typedef int x; enum x

这由预处理器扩展为如下代码:

typedef int FREE_IMAGE_FILTER;
enum FREE_IMAGE_FILTER {
 FILTER_BOX = 0,
 FILTER_BICUBIC = 1,
[...]

这是做什么的?typedefa和 anenum同名是否合法?而且不enum兼容int吗?为什么 FreeImage 会这样做?

4

2 回答 2

7

结构、联合和枚举的名称存在于它们自己的命名空间中。这就是为什么您可以声明一个与实际 //同名的//struct变量。unionenumstructunionenum

并且它不是必须与整数兼容的完整名称enum(例如,enum X我的意思是),而是枚举中的名称。X

于 2013-07-29T07:45:34.467 回答
0

引用C99 N1256 草案6.2.1“标识符范围”:

一个标识符可以表示一个对象;一个函数;结构、联合或枚举的标签或成员;类型定义名称;标签名称;宏名;或宏参数。

这意味着在:

typedef int id;

id是一个标识符。

从 6.2.3 “标识符的命名空间”开始:

开始报价

如果一个特定标识符的多个声明在翻译单元中的任何位置可见,则句法上下文消除了引用不同实体的用法的歧义。因此,各种类别的标识符都有单独的名称空间,如下所示:

  • 标签名称(通过标签声明和使用的语法消除歧义);
  • 结构、联合和枚举的标签(通过遵循任何关键字 struct、union 或 enum 来消除歧义);
  • 结构或工会的成员;每个结构或联合对其成员都有一个单独的名称空间(通过用于通过 . 或 -> 运算符访问成员的表达式的类型来消除歧义);
  • 所有其他标识符,称为普通标识符(在普通声明符中声明或作为枚举常量声明)。

结束报价

所以在:

typedef int id;
enum id {ID0};
  • 第一个id是普通标识符
  • 第二个是标签标识符

两者可以和平共处。

另一方面,我们不能这样做:

typedef int id;
int id;

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

于 2015-05-28T20:13:03.820 回答