这个宏语句是合法的C ++还是别的什么?如果它是合法的,它是如何工作的

时间:2011-07-29 23:11:00

标签: c++ macros webkit c-preprocessor

WebKit有很多这样的预处理器行: #if MACRO1(MACRO2)

例如:

#if PLATFORM(MAC) || (PLATFORM(QT) && USE(QTKIT))
#include "MediaPlayerPrivateQTKit.h"
#if USE(AVFOUNDATION)
#include "MediaPlayerPrivateAVFoundationObjC.h"
#endif
...

所以我的第一个想法是它们是类似函数的宏,但是我看不出它是如何工作的,而且我在源代码的任何地方都找不到这些宏的#defines。

我问另一位工程师它是什么,他从来没有见过像#if之前那样的多个宏。 我发现这个wiki page谈到了它们,但我仍然不清楚它们来自哪里,

那么我的问题是:这是有效的C ++还是在代码中被其他工具/语言替换为CMake或其他东西,如果它是有效的C ++是否有人知道有关此问题的说明?

我是C ++静态分析工具的支持工程师,该工具未处理此语法。一位客户要求我们处理它,但如果我要把它带给高级工程师,我不想听起来像个白痴:)所以如果有人知道的话,我会喜欢这个细节。

3 个答案:

答案 0 :(得分:5)

正如在wiki中所提到的,在root/trunk/Source/JavaScriptCore/wtf/Platform.h中我们得到了每个定义的定义。例如,PLATFORM宏定义为:

#define PLATFORM(WTF_FEATURE) \
       (defined WTF_PLATFORM_##WTF_FEATURE \
        && WTF_PLATFORM_##WTF_FEATURE)

WTF_FEATURE的值将替换为平台名称,以创建名为WTF_PLATFORM_WTF_FEATRE的宏。例如,将WTF_FEATURE作为MAC传递到宏中,最终会扩展WTF_PLATFORM_MAC。与逻辑defined结合的预处理器AND指令基本上是询问是否定义了该宏,如果已定义,则其值是否为“真”值。您可以在预处理器的其他位置使用此宏,如:

#ifdef __APPLE__
#define WTF_PLATFORM_MAC 1
#end if

#define PLATFORM(WTF_FEATURE) \
       (defined WTF_PLATFORM_##WTF_FEATURE \
        && WTF_PLATFORM_##WTF_FEATURE)

#if PLATFORM(MAC)
//...some code
#end if

您不会在C ++代码本身中使用它,如

if (PLATFORM(MAC))
{
    //...some code
}

这将导致编译器出现大量错误,因为defined不是C ++关键字,并且在C ++代码中评估和替换宏最终会转储defined预处理器指令到任何直接调用宏的C ++代码。这不是有效的C ++。

感谢约翰内斯指出其中的一些问题。

答案 1 :(得分:3)

#if指令粗略地通过替换所有宏,然后替换0剩下的所有标识符和关键字,然后根据C ++语言的规则处理剩下的具有常量表达式(这些规则的子集适用于替换中剩下的内容 - 非常少:))。

如果PLATFORM(MAC)被定义为1,则MAC可能会产生1,如果MAC未定义PLATFORM,则#define PLATFORM(X) X 简单地定义为

MAC

生成的0是一个标识符,稍后将被X替换。它们更有可能将PLATFORM连接到MAC之类的东西,以支持以16.1为参数的多个查询,测试是否存在不同的宏。作为“C ++ Static Analysis”工具的开发人员,您可能可以访问C ++规范。看看{{1}}条款。

答案 2 :(得分:0)

定义可能来自构建脚本。大多数C ++编译器允许您在命令行上定义宏。

我可以看到在您的示例中定义USE宏的一种方法是:

#define USE_QTKIT 1
#define USE(x) USE_ ## x

或者也许喜欢:

gcc -DUSE_QTKIT=1 '-DUSE(x)=USE_ ## x'