2014-01-10 85 views
1
#include <stdio.h> 

#define tokenpaster(n) printf ("token" #n " = %d", token##n) 

int main(void) 
{ 
    int token34 = 40; 

    tokenpaster(34); 
    return 0; 
} 

The output is标记粘贴

token34 = 40 

笔者说:

怎么回事,因为这个例子的结果是来自前处理实际输出如下:

printf ("token34 = %d", token34); 

如何将token##n转换为token34?它应该不是token#34

+0

“令牌” #n被preprocesed为“token34” - 没关系。您的问题与您的示例代码不同 –

回答

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如果,在一个函数宏的替换列表,一个参数被立即之前 或然后是##预处理令牌,参数被相应的 参数的预处理令牌序列替换(...)

+1

有人可以解释downvote? – Groo

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); 

和编译器catenates格式字符串,所以最终的结果是:

printf ("token34 = %d", token34); 
+1

@EliasVanOotegem不,双重哈希本身是一个运算符,而不是单哈希运算符的双重应用程序(请参阅C11第6.10.3.3节)。如果是的话它会扩展到'token#“34”',这反过来(我猜)会扩展到'token“\”34 \“”'并导致语法错误。 – Kninnug