1

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

假设我有以下代码:

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

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

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

4

5 回答 5

3

DEF将扩大给#if (1, 2, 3 > 3)。因为,具有低优先级,“做”任何事情的唯一表达式3 > 3当然是错误的。

于 2015-08-18T11:37:08.873 回答
2

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

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

表单的预处理指令

# if 常量表达式换行组选择

# elif 常量表达式换行组选择

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

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

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

脚注 115 是:

sizeofor运算符的操作数_Alignof通常不被计算(6.5.3.4)。

于 2015-08-18T11:55:37.050 回答
1

C++11 标准允许逗号操作符,但这种改变只是无意的。诸如 Clang 和 GCC evaluate 之类的实现#if (1,0),但它们会发出警告-pedantic,尽管后果肯定是轻微的,但它们是它们对非法预处理器构造的典型响应。他们对宏重新定义做同样的事情,这是完全有害的。

警告:#if [-Wpedantic] 操作数中的逗号运算符

计划将“功能”(DR 1436)从标准中删除,但对于如何执行此操作或如何处理预处理器标准的维护仍存在不确定性。

(需要明确的是,在 C++11 之前的 C 语言和 C++ 中,逗号被明确禁止用于常量表达式。请参阅 cremno 的回答。无意中的更改是删除了通用语言的“常量表达式不得包含……”,但是无需为预处理器添加规则。)

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

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

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

于 2015-08-18T12:18:40.423 回答
1
#define DEF 1,2,3
#if (DEF > 3)
#endif

上述 if 条件将失败。原因 3 > 3 是错误的。可能你可以把它说成

#define DEF 1,2,3
#if (DEF == 3)
#endif
于 2015-08-18T11:36:38.190 回答
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价值。

于 2015-08-18T11:42:09.727 回答