C预处理器中是否存在逻辑短路?

时间:2014-06-04 12:35:12

标签: c++ c gcc

关于#if指令的gcc docs for cpp解释:

  

[...]和逻辑运算(&&和||)。后两者遵守标准C的通常短路规则。

这是什么意思?在预处理过程中没有表达式的评估,那么它如何被短路呢?

4 个答案:

答案 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)

  

在预处理过程中没有表达式的评估,那么它如何被短路?

是的,在预处理期间有表达式评估

C11:6.10.1条件包含(p4):

  

评估之前,预处理令牌列表中的宏调用将成为......

脚注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)

评估宏观条件是预处理的一部分(主要部分),因此它发生并且短路在那里是有意义的。您可以看到其他答案的示例。

  

条件是指示预处理器选择的指令   是否在最终令牌流中包含一大块代码   传递给编译器。 预处理器条件可以测试算术   表达式,或者名称是否定义为宏,或两者都定义   同时使用特殊定义的运算符。

此外,它可以减少编译时间。改变以下评估可以加快编译速度(编译器实现的速度)。