预处理器指令中的逗号运算符

时间:2015-08-18 11:30:50

标签: c c-preprocessor preprocessor-directive comma-operator

这是一个需要更深入理解的问题。

我们说我有以下代码:

{{1}}

如果我是对的,则if应始终为true,因为1和2是没有影响的表达式,只会检查3。 (这至少应该在正常的 C / C ++ - 代码中)

但这是正确的还是有任何理由我为什么要考虑1和2呢?我在一些代码中看到了它,我不确定这是否有任何意义或影响。

5 个答案:

答案 0 :(得分:3)

DEF将展开以提供#if (1, 2, 3 > 3)。因为,的优先级较低,所以"的唯一表达式是"任何东西都是3 > 3,当然这是假的。

答案 1 :(得分:2)

您的示例代码并不严格符合。

从C11,6.10.1标准杆。 3(条件包含,语义):

  

表格的预处理指令

     

# if 常量表达式新行组 opt

     

# elif 常量表达式新行组 opt

     

检查控制常量表达式是否计算为非零

然而6.6标准杆3(常量表达式,约束)说:

  

常量表达式不应包含赋值,递增,递减,函数调用或逗号运算符,除非它们包含在未评估的子表达式中。 115)

脚注115是:

  

sizeof _Alignof 运算符的操作数通常不会被评估(6.5.3.4)。

答案 2 :(得分:1)

#define DEF 1,2,3
#if (DEF > 3)
#endif

以上if条件将失败。原因3> 3是假的。 可能你可以把它作为

#define DEF 1,2,3
#if (DEF == 3)
#endif

答案 3 :(得分:1)

是的,你是正确的,因为前两个是虚拟表达式,只有第三个表达式才会被实际评估。

考虑代码:

#define DEF 1,2,3
#if (DEF > 3)
#endif

将被视为:

#if (1,2,3 > 3)
#endif

,的优先级低于>,因此3 > 3会导致0。然后,#if (1,2,0)肯定会评估为#if (0),其值始终为false

答案 4 :(得分:1)

C ++ 11标准允许逗号运算符,但更改只是无意中。像Clang和GCC这样的实现会评估#if (1,0),但是他们会在-pedantic下发出警告,虽然这肯定是一个温和的结果,但它们是对非法预处理器结构的典型响应。他们对宏观重新定义做了同样的事情,这是完全有害的。

  

警告:#if [-Wpedantic]

操作数中的逗号运算符

“功能”已安排(DR 1436)从标准中删除,但是如何执行此操作或如何一般地处理预处理器标准的维护存在持续的不确定性。 / p>

(很明显,在C ++ 11之前的C语言和C ++中,逗号被特别禁止使用常量表达式。请参阅cremno的答案。无意中的更改是删除“常量表达式不应包含......”语言,但没有为预处理器添加规则。)

我已经提议(N4220)对预处理器规范进行了全面更新,但是在没有正式审核的情况下,它已在一个小组委员会中停滞不前。尽管如此,一些感兴趣的委员会成员(来自Clang,GCC和IBM XLC)确实对其进行了审核,并且普遍认为该论文中的调整反映了该标准的真实意图。从该论文的§4.4开始,

  

请注意,即使在括号内也不允许使用逗号运算符。

实际上,不,逗号运算符既不便携也不面向未来。有几个人考虑过这个问题并同意你不应该在那里使用它。但是,遵循表达式评估规则,您12被忽略是正确的。