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