##(双散列)在预处理器指令中做什么

What does ## (double hash) do in a preprocessor directive?

本文关键字:指令 处理器 什么 预处理      更新时间:2023-10-16
#define DEFINE_STAT(Stat) 
struct FThreadSafeStaticStat<FStat_##Stat> StatPtr_##Stat;

上面这句话取自虚幻4,我知道我可以在虚幻论坛上问一遍,但我认为这是一个普通的C++问题,值得在这里问。

我知道第一行定义了一个宏,但我不太熟悉C++中的预处理器恶作剧,所以我在那里很困惑。逻辑告诉我反斜线意味着声明继续到下一行。

FThreadSafeStaticStat看起来有点像一个模板,但里面有#,还有我以前在C++中从未见过的语法

有人能告诉我这是什么意思吗?我知道你可能无法访问虚幻4,但这只是我不理解的语法。

##是用于级联的预处理器运算符。

所以如果你使用

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");
}

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

Stumped?

当预处理器在此代码上被调用时,

  • 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()

TLDR;##用于级联,#用于字符串化(来自cppreference(。

##连接连续的标识符,当您想将函数作为参数传递时,它很有用。这里有一个例子,其中foo接受函数自变量作为其第一个自变量,运算符ab作为第二个和第三个自变量:

#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=%dn", a, b,  foo(my_sum, a, b));  // 2+3=5
    printf("%d-%d=%dn", a, b, foo(my_minus, a, b)); // 2-3=-1
    return 0;
}

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

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