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

not*_*ser 28 c c++ gcc

cppgcc文档解释了该#if指令:

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

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

jth*_*ill 26

非常简单:未定义的宏的数值为零,除零是非法的.

#if FIXEDSIZE && CHUNKSIZE/FIXEDSIZE > 42
#define USE_CELLPOOL
#endif
Run Code Online (Sandbox Code Playgroud)

#if确实将其余部分计算为整数常量表达式.您的链接文档开始:

'#if'指令允许您测试算术表达式的值,而不仅仅是一个宏的存在.

这不是gcc扩展,标准的语法#if

#ifconstant-expression new-line groupopt.

C99预处理器将所有常量视为[u]intmax_t.


Jef*_*mas 9

他们所指的是&&||运营商#if

#if defined (AAA) || defined (BBB)
Run Code Online (Sandbox Code Playgroud)

如果defined (AAA)已定义,则defined (BBB)永远不会评估.


UPDATE

因此,运行计算将被短路.例如,如果您构建-Wundef以警告未定义宏的使用.

#if defined FOO && FOO > 1000
#endif

#if FOO > 1000
#endif
Run Code Online (Sandbox Code Playgroud)

会导致

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.
Run Code Online (Sandbox Code Playgroud)

因此第一个版本不会生成未定义的宏警告,因为FOO > 1000未进行评估.


老房子

如果第二部分是具有副作用的宏,则这变得重要.不会评估宏,因此不会产生副作用.


为了避免宏观滥用,我会给出一个有点理智的例子

#define FOO
#define IF_WARN(x) _Pragma (#x) 1
#if defined(FOO) || IF_WARN(GCC warning "FOO not defined")
#endif
Run Code Online (Sandbox Code Playgroud)

现在我构建了这个例子,现在我遇到了一个问题.IF_WARN总是被评估.

呵呵,需要更多的研究.


好吧......现在我再读一遍.

宏.在实际计算表达式的值之前,表达式中的所有宏都会被展开.

  • @JefferyThomas:比如? (11认同)
  • 它有什么变化,因为预处理器没有副作用?编辑:似乎我错了,所以我想看一个样本:) (3认同)
  • @RudyVelthuis:问题的全部要点是询问是否评估一个表达式而另一个表达式是否重要; 这个答案只是教导什么是短路,甚至没有_attempting_来回答这个问题.至于你的上一条评论,"预处理器表达式"和"C++表达式"是两个非常不同的东西,我认为OP很明确指的是哪一个. (3认同)

hac*_*cks 5

预处理的时候没有对表达式求值,那么怎么短路呢?

是的,在预处理期间对表达式进行评估

C11:6.10.1 有条件包含(p4):

在评估之前,预处理标记列表中的宏调用将变为...

在脚注 166 中:

因为在转换阶段 4 期间计算控制常量表达式,所以所有标识符....

这些陈述清楚地证明在预处理存在对表达式的求值。必要条件是控制表达式必须计算为整数值。
现在,操作符&&and||将遵守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;
}
Run Code Online (Sandbox Code Playgroud)