这个宏语句合法吗 C++或者其他什么?如果它是合法的,它是如何运作的

发布于 2024-11-27 04:58:40 字数 753 浏览 4 评论 0原文

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

例如:

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

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

我问另一位工程师这是什么,他以前从未见过在 #if 中像这样使用多个宏。 我发现这个 wiki 页面 讨论了它们,但仍然不清楚我他们来自哪里,

所以我的问题是:这是有效的 C++ 还是它在代码中被其他工具/语言(如 CMake 或其他东西)替换,如果它是有效的 C++,是否有任何人都知道的规范关于这个?

我是 C++ 静态分析工具的支持工程师,该工具不处理此语法。一位客户要求我们处理这个问题,但如果我要把这个问题交给高级工程师,我不想听起来像个白痴:)所以如果有人知道的话,我希望了解具体情况。

WebKit has a lot of pre-processor lines like this:
#if MACRO1(MACRO2)

For example:

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

So my first thought was that they were function-like macros, but I can't see how that would work, and I couldn't find any #defines for these macros anywhere in the source code.

I asked another engineer what it was and he's never seen multiple macros used like that inside a #if before either.
I found this wiki page that talks about them but it still wasn't clear to me where they come from,

So my question then: Is this valid C++ or is it being replaced in the code by another tool/language like CMake or something else, and if it is valid C++ is there a spec anyone is aware of that talks about this?

I'm a support engineer for a C++ Static Analysis tool that isn't handling this syntax. A customer asked us to handle it, but if I'm going to take this to the senior engineer I'd like to not sound like an idiot :) So I'd like the nitty gritty if anyone knows it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

正如维基中提到的,在 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 的扩展。预处理器define指令与逻辑AND相结合基本上是询问该宏值是否已定义,如果已定义,则其值是否为“true”值。您可以在预处理器的其他地方使用此宏,例如:

#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
}

这会导致编译器出现一堆错误,因为 define 不是 C++ 关键字, C++ 代码中宏的求值和替换最终会将定义的预处理器指令转储到直接调用该宏的任何 C++ 代码中。那不是有效的 C++。

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

As mentioned in the wiki, in root/trunk/Source/JavaScriptCore/wtf/Platform.h we get a definition for each of these defines. For instance, the PLATFORM macro is defined as:

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

The value of WTF_FEATURE will be replaced by the platform name to create some macro named WTF_PLATFORM_WTF_FEATRE. For instance, with WTF_FEATURE passed into the macro as MAC, you would end up with a expansion of WTF_PLATFORM_MAC. The pre-processor defined directive combined with the logical AND is basically asking whether that macro value defined, and if it is defined, if its value is a "true" value. You would use this macro somewhere else in the pre-processor like:

#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

You wouldn't use it within C++ code itself like

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

that would cause a bunch of errors from the compiler since defined is not a C++ keyword, and the evaluation and replacement of the macro within C++ code would end up dumping the defined pre-processor directive into any C++ code that directly called the macro. That's not valid C++.

Thanks you to Johannes for pointing out some of these issues.

悍妇囚夫 2024-12-04 04:58:40

#if 指令的大致工作原理是替换所有宏,然后替换 0 剩下的所有标识符和关键字,然后根据规则处理剩下的常量表达式C++ 语言的规则(这些规则的子集适用于替换后剩下的内容 - 很少:))。

因此,如果 MAC 定义为 1PLATFORM(MAC) 可能会产生 1,并且 MAC 如果未定义,如果 PLATFORM 简单地定义为

#define PLATFORM(X) X

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

The #if directive roughly works by replacing all macros, and then replacing all identifier and keywords of what's left by 0 and afterwards processing what's left has a constant expression according to the rules of the C++ language (the subset of those rules applicable to what's left from that replacing - quite little :)).

So PLATFORM(MAC) may yield a 1 if MAC is defined to be 1, and a MAC if it is not defined, if PLATFORM is simply defined as

#define PLATFORM(X) X

The resulting MAC is an identifier and will later be replaced by 0. It's more likely that they are concatenating the X to something like PLATFORM, so as to support multiple queries with MAC as argument, testing for existence of different macros. As a developer of a " C++ Static Analysis" tool you probably have access to the C++ spec. Take a look at clause 16.1.

生寂 2024-12-04 04:58:40

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

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

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

或者可能像:

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

The definitions may be coming from the build scripts. Most C++ compilers let you define macros on the command line.

One way I can see to define a USE macro like in your example would be:

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

Or maybe like:

gcc -DUSE_QTKIT=1 '-DUSE(x)=USE_ ## x'
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文