11

我有一个程序。

#include <stdio.h>

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

int main()
{
      printf("%s\n",h(f(1,2)));
      printf("%s\n",g(f(1,2)));
      return 0;
}

该程序正常工作并输出如下:

12
f(1, 2)

我不明白编译器如何给出这个输出。

# ina##b和的作用是什么#a

4

3 回答 3

12

##两个标记连接在一起。

重要的是它只能在预处理器中使用。

#运算符用于对标记进行字符串化。

例如:-

#(a ## b)哪个变成#ab哪个变成"ab"

所以 h(f(1,2)) 变成 "f(1,2)"

另请注意,#and##是两个不同的运算符。

预处理器运算符##提供了一种在宏扩展期间连接实际参数的方法。如果替换文本中的参数与## 相邻,则将参数替换为实际参数,删除## 和周围的空白,并重新扫描结果。

另请检查此串联以获取更多详细信息。

这里:-

串化

有时您可能希望将宏参数转换为字符串常量。参数不会在字符串常量内被替换,但您可以使用'#' 预处理运算符来代替。当宏参数与前导 `#' 一起使用时,预处理器将其替换为实际参数的文字文本,并转换为字符串常量。与普通参数替换不同,参数不是首先进行宏扩展的。这称为字符串化。

没有办法将参数与周围的文本组合在一起并将其全部字符串化。相反,您可以编写一系列相邻的字符串常量和字符串化参数。预处理器将用字符串常量替换字符串化的参数。然后,C 编译器会将所有相邻的字符串常量组合成一个长字符串。

于 2013-10-05T13:41:30.237 回答
4

##称为“标记粘贴”运算符或“合并”运算符,可用于组合两个标记以形成实际参数。

#称为字符串化运算符,它“将宏参数转换为字符串文字而不扩展参数定义”。

这些通常称为预处理器运算符。还有一些像这样的预处理器操作符。查看 C 中的预处理器运算符 ( http://msdn.microsoft.com/en-us/library/wy090hkc.aspx ) 以获得更多解释。


另请查看http://msdn.microsoft.com/en-us/library/3sxhs2ty.aspx和该页面的“另请参阅”部分,了解有关 C 预处理器的更多信息。

于 2013-10-05T13:53:19.077 回答
4

让我为你分解一下:

#define f(a,b) a##b //2 this macro is evaluated first with a = 1 and b = 2 it concatenates them and returns 12
#define g(a)   #a //4 g turns 12 into "12" (string)
#define h(a) g(a) //3 back to h which now has a = 12 and call g()

int main()
{
      printf("%s\n",h(f(1,2)));//1 printf calls the macro h() and gives it the macro f() as an argument 
      printf("%s\n",g(f(1,2)));// g here turns f(1,2) into "f(1,2)" (string)
      return 0;
}
于 2013-10-05T14:00:32.543 回答