##(double hash)在预处理器指令中做了什么?

Dav*_*son 77 c c++ concatenation c-preprocessor

#define DEFINE_STAT(Stat) \
struct FThreadSafeStaticStat<FStat_##Stat> StatPtr_##Stat;
Run Code Online (Sandbox Code Playgroud)

上面这行来自虚幻4,我知道我可以在不真实的论坛上问过它,但我认为这是一个普遍的C++问题,值得在这里提出.

我理解第一行定义了一个宏,但是我不熟悉C++中的预处理器恶作剧,所以我迷失在那里.逻辑告诉我反斜杠意味着声明继续到下一行.

FThreadSafeStaticStat看起来有点像模板,但是那里正在进行#和C++中我从未见过的语法

有人能告诉我这意味着什么吗?我知道您可能无法访问Unreal 4,但这只是我不理解的语法.

Sus*_*Pal 151

## 是串联的预处理器运算符.

所以,如果你使用

DEFINE_STAT(foo)

在代码中的任何地方,它都被替换为

struct FThreadSafeStaticStat<FStat_foo> StatPtr_foo;

在编译代码之前.

这是我的博客文章中的另一个例子,可以进一步解释这一点.

#include <stdio.h>

#define decode(s,t,u,m,p,e,d) m ## s ## u ## t
#define begin decode(a,n,i,m,a,t,e)

int begin()
{
    printf("Stumped?\n");
}
Run Code Online (Sandbox Code Playgroud)

该程序将成功编译和执行,并产生以下输出:

Stumped?
Run Code Online (Sandbox Code Playgroud)

当预处理器处理此代码时,

  • begin 被替换为 decode(a,n,i,m,a,t,e)
  • decode(a,n,i,m,a,t,e) 被替换为 m ## a ## i ## n
  • m ## a ## i ## n 被替换为 main

因而有效地begin()被替换为main().

  • 我没想到会想到这么多学习##的行为,但我想现在我永远不会忘记它?那谢谢啦. (4认同)
  • 我花了一点时间才明白,但这是对这个问题的一个极好的答案。谢谢。 (3认同)
  • TL;DR 为什么 Stumped-&gt;Animate-&gt; 脑筋急转弯起作用的原因是函数“decode”被设置为具有输入“a”,“n”,“i”,“m”。这些输入映射到*变量*“s”、“t”、“u”、“m”。然后使用预处理器字符串连接指令`m ## s ## u ## t`将这些变量重新排列成正确的顺序,该指令接受输入“a”,“n”,“i”,“m”并重新排列字符通过更改*变量*“s”、“t”、“u”、“m”的顺序来创建单词“main”。我发现绘制值和变量以及它们之间的映射很有帮助。 (3认同)
  • 为什么 `decode(a,n,i,m,a,t,e)` 被替换为 `m ## a ## i ## n`?那个怎么样?? (2认同)

hmo*_*rad 14

太长了;##用于连接和#字符串化(来自cppreference)。

连接##连续的标识符,当您想要将函数作为参数传递时,它非常有用。下面是一个示例,其中foo接受函数参数作为其第一个参数以及运算符aandb作为第二个和第三个参数:

#include <stdio.h>
enum {my_sum=1, my_minus=2};
#define foo(which, a, b) which##x(a, b)
#define my_sumx(a, b) (a+b)
#define my_minusx(a, b) (a-b)

int main(int argc, char **argv) {
    int a = 2;
    int b = 3;
    printf("%d+%d=%d\n", a, b,  foo(my_sum, a, b));  // 2+3=5
    printf("%d-%d=%d\n", a, b, foo(my_minus, a, b)); // 2-3=-1
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

连接#参数并将输出括在引号中。例子是:

#include <stdio.h> 
#define bar(...) puts(#__VA_ARGS__)
int main(int argc, char **argv) {
    bar(1, "x", int); // 1, "x", int
    return 0;
}
Run Code Online (Sandbox Code Playgroud)