#include <stdio.h>
#define tokenpaster(n) printf ("token" #n " = %d", token##n)
int main(void)
{
int token34 = 40;
tokenpaster(34);
return 0;
}
token34 = 40
作者说:
如何发生,因为此示例导致预处理器的以下实际输出:
printf ("token34 = %d", token34);
token##n
如何转换为token34
?它不应该是token#34
吗?
答案 0 :(得分:2)
预处理程序语句中的双哈希将两个参数粘合在一起。因此token##n
变为token##34
变为token34
。单个哈希对其参数进行字符串化。因此#n
变为"34"
。因此整个宏观扩张如下:
tokenparser(34);
->
printf ("token" #n " = %d", token##n);
->
printf ("token" "34" " = %d", token##34);
->
printf ("token" "34" " = %d", token34);
并且编译器连接格式字符串,因此最终结果为:
printf ("token34 = %d", token34);
答案 1 :(得分:0)
单个哈希前缀(#
)强制预处理器为stringify您的参数。双重哈希前缀(##
)只是粘贴参数并将其与前缀合并。
这意味着tokenpaster(34)
将扩展为:
printf ("token" "34" " = %d", token34)
^^^^ ^^
| |
| +---- pasted and merged
|
+---- enclosed in quotes
然后将这三个字符串文字部分合并为一个文字:
printf ("token34 = %d", token34)
根据the standard:
§6.10.3.2
#
运算符2如果在替换列表中,参数前面紧跟
#
预处理 令牌,两者都被单字符串文字预处理令牌取代 包含相应的预处理标记序列的拼写 论点。 (...)
和
§6.10.3.3
##
运算符2如果在类似函数的宏的替换列表中,紧接着一个参数 或者后跟
##
预处理令牌,参数将被相应的替换 参数的预处理标记序列(...)