为什么以下代码会编译?
#ifdef C++11
// ...
#endif
int main() {}
gcc 4.8.0给了我以下警告:
#if> #ifdef指令结束时的额外令牌
根据标准,宏名称只能包含字母,数字和下划线字符。
也许是因为这个?
ISO / IEC 14882:2011
16.1条件包含[cpp.cond]
6按顺序检查每个指令的条件。如果评估为 false(零),它控制的组被跳过:指令是 仅通过按顺序确定指令的名称进行处理 跟踪嵌套条件的级别;剩下的 指令的预处理令牌被忽略,另一个则被忽略 预处理组中的令牌。只有第一组控制 处理条件计算结果为真(非零)。如果没有 条件评估为真,并且有一个#else指令,即 由#else控制的组被处理;没有#else指令, 所有组,直到#endif被跳过.151
我无法正确理解这句话。
答案 0 :(得分:3)
就C ++而言,#ifdef C++11
是语法错误。没有规则说编译器必须拒绝具有语法错误的程序。
1.4实施合规性[intro.compliance]
可诊断规则集包含本国际标准中的所有语法和语义规则,但那些包含“无需诊断”的明确表示法或描述为“未定义行为”的规则除外。
[...]
如果程序包含违反任何可诊断规则或本标准中描述的构造的发生,如果实现不支持该构造,则符合条件的实现应发出至少一条诊断消息。 / p>
警告是诊断消息。编译器完全有权继续成功编译程序,只要它们确保它们向您显示一条诊断消息即可。由于编制者历来接受这样的指令,并且接受这些指令并不与标准的要求相冲突,他们继续这样做。
至少就GCC而言,您可以要求使用-pedantic-errors
选项使所有标准要求的诊断成为硬错误。
$ printf "#ifdef C++11\n#endif\n" | gcc -std=c++11 -pedantic-errors -E -x c++ -
# 1 "<stdin>"
# 1 "<command-line>"
# 1 "<stdin>"
<stdin>:1:9: error: extra tokens at end of #ifdef directive
答案 1 :(得分:1)
#ifdef
定义如下(取自§16.1)
# ifdef
标识符新行
使用类似regexp的表示法,标识符为:[a-zA-Z_][a-zA-Z_0-9]*
(*)
重点是:您声明的宏不是C++11
。它实际上是C
(见this live example)。预处理器忽略++11
部分。标识符后面唯一允许的字符(C
)是一个新行,但正如hvd的回答所述,从§1.4开始,语法错误只强制诊断消息,这里是警告;我认为这个而不是错误的唯一原因是与旧代码兼容,这些名称应该被使用。
另外:引用解释了#ifdef / #elif / #else / #endif
如何协同工作,而不是指定条件的方式。
我没有标准的副本。我使用草稿n3485作为答案。
(*)可以在标识符中包含实现定义的字符,但这不会影响您的问题。请注意,变量,类名,宏,...都遵循相同的标识符规则。