这段C代码是如何工作的?

6

a##b#a是什么?

  #define f(a,b) a##b
  #define g(a)   #a
  #define h(a) g(a)

  main()
  {
          printf("%s\n",h(f(1,2)));  //how should I interpret this?? [line 1]
          printf("%s\n",g(f(1,2)));  //and this? [line 2]
  }

这个程序是如何工作的?
输出为
12
f(1, 2)

现在我明白了a##b#a是如何工作的。但是为什么两种情况的结果不同呢(第一行和第二行)?


3
运行那个程序会发生什么?这样做有助于你理解正在发生的事情。 - Greg Hewgill
1
真的,玩一会儿那段代码就会豁然开朗。如果您有具体的问题,请随时在此提问。 - sharptooth
7个回答

19

## 运算符将两个标记连接在一起。它只能用于预处理器中。

f(1,2) 变成 1 ## 2 变成 12

仅使用#运算符,可以将标记转换为字符串:#a 变成 "a"。 因此,当预处理器完成后,g(f(1,2)) 变成 "f(1,2)"

h(f(1,2)) 实际上是 #(1 ## 2),在预处理器运行时变成 #12,最终变成 "12"


5

对于这样的问题(以及与预处理器有关的更多“现实世界”问题),我发现实际上阅读经过预处理后的代码非常有帮助。

如何做到这一点因编译器而异,但对于gcc,您可以使用以下命令:

$ gcc -E test.c

(snip)
main()
{
        printf("%s\n","12");
        printf("%s\n","f(1,2)");
}

因此,您可以看到符号已经被连接并转换为字符串。


为什么第二个printf输出的结果是"f(1,2)"而不是"12"? - Moeb
@hanifr:因为g()宏将其参数字符串化了,我猜是这个原因。 - unwind

4

a##b会将代码拼接在一起。

因此,f(1,2)将变成12。


2
这只是问题的一半。 - user181548

3

f(a,b)宏将其参数连接起来,g(a)将其参数转换为字符串,h(a)是g(a)的辅助宏。我认为它会输出:

12
f(1,2)

原因

原因在于 h(a) 宏会在将其参数传递给 g(a) 之前对其进行完全展开,而 g(a) 则会直接使用其参数而不进行展开。

这与 IT 技术有关。


为什么第二个printf输出的结果是"f(1,2)"而不是"12"? - Moeb
为什么会发生这种情况:“原因是h(a)宏在将其参数传递给g(a)之前会导致其参数被完全展开,而g(a)将直接采用其参数而不先进行展开。”? - Moeb

0

a##b 是将字面量 a 和 b 进行字符串拼接,因此 f(1,2) 的结果为 "12"

#a 是字符串字面量 a,因此 g(3) 的结果为 "3"


0

## 是宏连接运算符。例如,f(foo,bar) 相当于 foobar


0
#define f(a,b) a##b
#define g(a)   #a
#define h(a) g(a)

所以,## 直接将2个部分组合在一起,不管它们是什么类型... 给你一个例子.. printf("%d\n",f(1,2)); 你会得到12,这意味着f(1,2)是一个整数12。

    int a2 = 100;
    printf("%d\n",f(a,2));

这里的f(a,2)是标签。它指向您代码上下文中的一个标签,如果没有int a2 = 100,就会出现编译错误。 而#a将任何a转换为一个字符串... 然后是h(a) g(a) 这很奇怪... 当您调用h(a)时,它变成了g(a),并将a传递给g(a),首先解释了a是什么。所以,在您可以使用g(a)之前,a被转换为f(a,b) = a##b = 12。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接