我有一个程序。
#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)
我不明白编译器如何提供此输出。
a##b
和#a
中的#功能是什么?
答案 0 :(得分:12)
##
将两个令牌连接在一起。
重要的是它只能在预处理器中使用。
#
运算符用于字符串化标记。
例如: -
#(a ## b)
变为#ab
<{1}}成为"ab"
所以h(f(1,2))变为“f(1,2)”
另请注意,#
和##
是两个不同的运算符。
预处理程序运算符 ## 提供了一种连接实际的方法 宏观扩张期间的争论。如果一个参数在替换 文本与##相邻,参数由实际替换 参数,##和周围的空白区域被删除了 结果被重新扫描。
另请查看 Concatenation 了解详情。
来自here: -
<强>字串化强>
有时您可能希望将宏参数转换为字符串 不变。参数不会在字符串常量内替换,但是你 可以使用'#'预处理运算符。当一个宏参数 与前导“#”一起使用,预处理器将其替换为 实际参数的文字文本,转换为字符串常量。 与普通参数替换不同,参数不是 首先是宏观扩张。这称为字符串化。
无法将参数与周围文本组合在一起 将它们串联起来。相反,你可以写一系列相邻的 字符串常量和字符串化参数。预处理器会 用字符串常量替换字符串化的参数。 C 然后编译器将所有相邻的字符串常量合并为一个 长串。
答案 1 :(得分:4)
##
被称为“令牌粘贴”运算符,或“合并”运算符,可用于组合两个令牌以形成实际参数。
#
称为字符串化运算符,它“将宏参数转换为字符串文字而不扩展参数定义”。
这些通常称为预处理器操作符。还有一些像这样的预处理器运算符。查看C(http://msdn.microsoft.com/en-us/library/wy090hkc.aspx)中的预处理器操作符以获取更多说明。
同时结帐http://msdn.microsoft.com/en-us/library/3sxhs2ty.aspx以及该页面的“另请参阅”部分,了解有关C预处理器的更多信息。
答案 2 :(得分: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;
}