##(双哈希)在预处理器指令中做了啥?

Posted

技术标签:

【中文标题】##(双哈希)在预处理器指令中做了啥?【英文标题】:What does ## (double hash) do in a preprocessor directive?##(双哈希)在预处理器指令中做了什么? 【发布时间】:2014-05-23 09:28:00 【问题描述】:
#define DEFINE_STAT(Stat) \
struct FThreadSafeStaticStat<FStat_##Stat> StatPtr_##Stat;

以上代码取自 Unreal 4,我知道我可以在 unreal 论坛上提问,但我认为这是一个一般性的 C++ 问题,值得在这里提出。

我知道第一行定义了一个宏,但是我并不精通 C++ 中的预处理器恶作剧,所以我迷路了。逻辑告诉我反斜杠意味着声明继续到下一行。

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

谁能告诉我这是什么意思?我了解您可能无法访问 Unreal 4,但这只是我不了解的语法。

【问题讨论】:

您可以阅读有关## operator on cppreference 等内容 ## 是/可以称为连接运算符。 哦,太酷了!它解释了很多,谢谢。但是为什么要使用 struct 关键字呢?该行看起来更像是一个变量定义 据我所知,struct 引入了一个详细的类型说明符 正式名称为“token pasteing operator”,因为它结合了两个预处理token来产生另一个。请注意,它仅在结果是有效的预处理令牌时才有效,例如你不能用+ ## 3 来制造+3。 (但你当然可以+ 3,不用运营商) 【参考方案1】:

## 是用于连接的预处理运算符。

所以如果你使用

DEFINE_STAT(foo)

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

struct FThreadSafeStaticStat&lt;FStat_foo&gt; StatPtr_foo;

在你的代码被编译之前。

这是我的a blog post 的另一个示例,可以进一步解释这一点。

#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() 替换。

【讨论】:

我没想到会想那么多来学习##的行为,但我想现在我永远不会忘记它?所以谢谢。 花了我一秒钟的时间来关注它,但这是对这个问题的绝妙答案。谢谢。【参考方案2】:

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=%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;

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

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

【讨论】:

以上是关于##(双哈希)在预处理器指令中做了啥?的主要内容,如果未能解决你的问题,请参考以下文章

预处理器对“# <number> <filename>”做了啥?

Angular2:配对选择器在@Directive中做了啥

优化器在 Apache Pig 架构中做了啥?

哈希在python中做了啥?

*::(星号双冒号)在Ruby中做了啥?

~~(“双波浪号”)在 Javascript 中做了啥?