You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

预处理器#if中逻辑与(&&)未正确短路的跨编译器行为疑问

预处理器#if中逻辑与(&&)未正确短路的跨编译器行为疑问

各位好,最近碰到一个挺有意思的跨编译器差异问题,关于C预处理器#if里&&的短路行为,跟大家聊聊。

先看这段测试代码:

#if defined(FOO) && FOO(foo)
    #error "FOO is defined."
#else
    #error "FOO is not defined."
#endif

这段代码的预期逻辑应该是:如果FOO被定义,才去求值FOO(foo),否则直接走#else分支——毕竟&&应该有短路特性对吧?但不同编译器的处理结果完全不一样:

MSVC 19.38的输出

<source>(1): warning C4067: unexpected tokens following preprocessor directive - expected a newline
<source>(4): fatal error C1189: #error:  "FOO is not defined."

MSVC这里只给了个警告,然后正常走到了#else分支,抛出对应的#error。

ICX 2024.0.0 和 Clang 18.1的输出

<source>:1:21: error: function-like macro 'FOO' is not defined
    1 | #if defined(FOO) && FOO(foo)
      |                     ^
<source>:4:6: error: "FOO is not defined."
    4 |     #error "FOO is not defined."
      |      ^
2 errors generated.

这俩编译器直接报错,说函数式宏FOO未定义,说明它们没有短路&&右边的表达式,直接去解析了FOO(foo)。

GCC 14.1的输出

<source>:1:24: error: missing binary operator before token "("
    1 | #if defined(FOO) && FOO(foo)
      |                        ^
<source>:4:6: error: "FOO is not defined."

GCC则报了语法错误,同样是因为尝试解析FOO(foo)时发现FOO不是宏,导致表达式不合法。

按C标准的话,#if中的逻辑表达式应该遵循短路求值:当defined(FOO)为假时,右边的FOO(foo)不应该被求值。但从实际编译结果来看,不同厂商的编译器在预处理器阶段的实现差异还挺大的,这确实是个容易踩坑的细节。

备注:内容来源于stack exchange,提问作者Madagascar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.16 12:48:11