关于#if
指令的gcc docs for cpp解释:
[...]和逻辑运算(&&和||)。后两者遵守标准C的通常短路规则。
这是什么意思?在预处理过程中没有表达式的评估,那么它如何被短路呢?
答案 0 :(得分:26)
非常简单:未定义的宏的数值为零,除零是非法的。
#if FIXEDSIZE && CHUNKSIZE/FIXEDSIZE > 42
#define USE_CELLPOOL
#endif
#if
会将其余部分的行计算为整数常量表达式。您的链接文档开始于:
'#if'指令允许您测试算术表达式的值,而不仅仅是存在一个宏。
这不是gcc扩展,标准#if
的语法是
#if
constant-expression new-line group
<子>opt
子>
C99预处理器将所有常量视为[u]intmax_t
。
答案 1 :(得分:9)
他们所指的是&&
的{{1}}和||
运算符
#if
如果定义#if defined (AAA) || defined (BBB)
,则永远不会评估defined (AAA)
。
<强>更新强>
因此,运行计算将被短路。例如,如果使用defined (BBB)
构建以警告未定义宏的使用。
-Wundef
将导致
#if defined FOO && FOO > 1000
#endif
#if FOO > 1000
#endif
因此,第一个版本不会生成未定义的宏警告,因为未评估thomas:~ jeffery$ gcc foo.c -Wundef
foo.c:4:5: warning: 'FOO' is not defined, evaluates to 0 [-Wundef]
#if FOO > 1000
^
1 warning generated.
。
OLD MUSINGS
如果第二部分是具有副作用的宏,则这变得重要。不会评估宏,因此不会产生副作用。
为了避免宏观滥用,我会给出一个有点理智的例子
FOO > 1000
现在我构建了这个例子,现在我遇到了一个问题。始终会对#define FOO
#define IF_WARN(x) _Pragma (#x) 1
#if defined(FOO) || IF_WARN(GCC warning "FOO not defined")
#endif
进行评估。
好吧......现在我又读完了。
宏。在实际计算表达式的值之前,表达式中的所有宏都会被扩展。
答案 2 :(得分:4)
在预处理过程中没有表达式的评估,那么它如何被短路?
是的,在预处理期间有表达式评估。
评估之前,预处理令牌列表中的宏调用将成为......
脚注166:
因为在翻译阶段4 期间评估了控制常量表达式,所有标识符....
这些陈述清楚地证明在预处理中有表达式的评估。必要条件是控制表达式必须求值为整数值
现在,运算符&&
和||
将遵循GNU doc中所述的标准C的常规短路规则。
现在使用和不使用//
运行此程序并查看结果以查看短路行为:
#include<stdio.h>
#define macro1 1
//#define macro2 1
int main( void )
{
#if defined (macro1) && defined (macro2)
printf( "Hello!\n" );
#endif
printf("World\n");
return 0;
}
答案 3 :(得分:3)
评估宏观条件是预处理的一部分(主要部分),因此它发生并且短路在那里是有意义的。您可以看到其他答案的示例。
条件是指示预处理器选择的指令 是否在最终令牌流中包含一大块代码 传递给编译器。 预处理器条件可以测试算术 表达式,或者名称是否定义为宏,或两者都定义 同时使用特殊定义的运算符。†
此外,它可以减少编译时间。改变以下评估可以加快编译速度(编译器实现的速度)。