C ++预处理器#define-ing a keyword。标准是否符合标准?

时间:2010-04-28 01:04:58

标签: c++ c-preprocessor

帮助解决this question about bool and 1评论中正在进行的辩论:

符合标准的C ++预处理器是否允许使用#define重新定义语言关键字?如果是这样,符合标准的C ++预处理器是否允许这样做?

如果C ++程序重新定义了一个语言关键字,那么该程序本身是否符合标准?

3 个答案:

答案 0 :(得分:21)

在C ++中,最接近禁止#define关键字的是§17.4.3.1.1/ 2,它只允许在包含标准库头的翻译单元中使用它:

  

包含标头的翻译单元不应包含定义在该标头中声明或定义的名称的任何宏。此类翻译单元也不应为与关键字词汇相同的名称定义宏。

该段落的第二句已在C ++ 0x中更改为彻底禁止#define关键字(C ++ 0xFCD§17.6.3.3.1): < / p>

  

翻译单元不得#define或#undef名称与关键字词汇相同。   

编辑正如Ken comments to his answer中Ken Bloom所指出的那样,规则在C ++ 0x中没有改变;文本刚刚被重新排列,以迷惑像我这样的人。 : - )

答案 1 :(得分:5)

2005-10-19 C++ working draft工作(因为我没有标准的方便):

第16.3节将#define的语法定义为#define identifier replacement-list-newline(类似对象的宏)或以#define identifier lparen开头的几种结构之一(类似函数的宏)。 identifier在第2.10节中定义为identifier-nondigit | identifier identifier-nondigit | identifier digit。第2.11节指出某个标识符列表在编译阶段7(第2.1节)中无条件地被视为关键字,因此我得出结论,因此在第4阶段(即预处理器扩展)中不对它们进行特殊处理。 因此,标准似乎要求预处理器允许您重新定义语言关键字(在第2.11节中列出)

但是,预处理器有一个自己的关键字,即defined,以及一个预定义宏列表(第16.8节)。第16.8节声明如果重新定义这些行为,则行为未定义,但不禁止预处理器将这些行为识别为宏名称。

答案 2 :(得分:1)

根据C ++ 11 [macro.names],这是不允许的:

  

翻译单元不得#define#undef在词汇上与关键字,表3中列出的标识符或7.6中描述的属性标记完全相同的名称。

“表3中列出的标识符”是finaloverride;而属性标记是[[fallthrough]]中的标识符,依此类推。

此子句仍是最新标准。