为啥在预处理器定义中使用 if 语句?

Posted

技术标签:

【中文标题】为啥在预处理器定义中使用 if 语句?【英文标题】:Why using if statements in preprocessor defines?为什么在预处理器定义中使用 if 语句? 【发布时间】:2014-06-12 14:00:38 【问题描述】:

在探索源代码包时,我发现一些 if 语句是由预处理器指令定义的,然后在代码中使用,如下例所示:

#ifdef _WIN32
    #define OSisWindows() true
    #define OSisLinux() false
#elif defined(__linux__)
    #define OSisLinux() true
    #define OSisWindows() false
#endif

if ( OSisWindows() )

// do something


if ( OSisLinux() )

// do something else

使用这个和像_WIN32__linux__ 这样的简单定义有区别吗?

【问题讨论】:

Eww,他们只是想模仿功能,但 bool OSisWindows() return true; 也可以。 真正的函数实际上会更好地工作:如果我没记错的话,在参数列表括号之前放置空格(应该允许)将导致宏标记无法匹配。 @chris:如果这些特定函数被大量使用,那么它可能会影响性能,因为函数调用本身会占用一些资源。当然,您可以直接使用inline,这也不是问题。 @wolfPack88,没有机会。无论有没有明确的inline,优化器都会跳过它。 @FrédéricHamidi:您可以调用类似函数的宏,在名称和左括号之间使用空格。你只是不能定义一个这样的。为了防止“调用”上的宏扩展,您需要用括号括住名称:(OSisWindows)() 【参考方案1】:

好吧,您不能直接在代码中使用宏,例如:

if ( _WIN32 ) 
    ...

例如在 linux 上,因为它没有定义,所以它们只是将宏映射到布尔表达式。

最后,这确实是一个风格决定……他们当然可以这样做:

#ifdef _WIN32
    ...
#endif

【讨论】:

如果它是#define _WIN32 1 或其他东西,你可以。不过,我不确定是否有任何保证。 是的,刚刚编辑了我的答案......在Windows上它被定义为1,所以它可以工作,但在其他平台上它不会被定义...... 未定义的情况可以像if (_WIN32+0)一样处理 如果 _WIN32 未定义则不会编译 您可以输入您的代码:#ifndef _WIN32 #define _WIN32 0 #endif。但在这一点上,我只是很难。【参考方案2】:

假设定义了宏,使用if..else 语句优于#if ..#else 指令的优势是所有代码路径都在第一种情况下编译,因此如果出现编译错误,编译器能够在所有代码路径中查看它们。当然这并不总是可行的,因为某些代码路径可能是平台相关的代码。

【讨论】:

【参考方案3】:

除了已经编写的内容之外,还有另一层抽象。例如,如果_WIN32 的语法发生变化,或者您想在不依赖标志的情况下为 Windows 显式编译,则必须更改完整代码,以防您直接使用 _WIN32。在这种情况下,您只需更改预处理器指令即可。

【讨论】:

【参考方案4】:

使用这个和像 _WIN32 或 linux 这样的简单定义有区别吗?

不,这是简单的宏滥用。

【讨论】:

以上是关于为啥在预处理器定义中使用 if 语句?的主要内容,如果未能解决你的问题,请参考以下文章

预处理器指令

为啥 C 预处理器不忽略它跳过的块中的无效指令?

预处理器中的 C# 宏定义

删除 C# 二进制文件中未使用的预处理器符号

#if 定义的预处理器运算符中的括号是啥意思?

#if 和 #ifdef Objective-C 预处理器宏有啥区别?