2016-08-16 102 views
3

从C语言程序设计,通过KRC嵌套宏和##

#define cat(x, y)  x ## y 

通话cat(var, 123)产量var123。但是,呼叫 cat(cat(1,2),3)未定义:##的存在阻止 外部呼叫的参数被扩展。因此它 产生标记字符串cat ( 1 , 2 )3)3(第一个参数的最后一个标记与第二个标记的第一个标记 的连接)不是合法标记。

如果引入宏定义的第二级,

#define xcat(x, y)  cat(x,y) 

事情的工作更加顺利; xcat(xcat(1, 2), 3)确实产生 123,因为xcat本身的扩展本身不涉及 ##算子。

##的性质是什么,使两个例子有所不同?

为什么第一个示例中的内部cat(1,2)未展开,而第二个示例中的内部xcat(1,2)是?

谢谢!

回答

1

这是宏##运算符的一个不太为人所熟知的特性,它禁止进一步扩展其参数(它只是将它们视为普通字符串)。从GCC预处理器文档的摘录:

...与字串,实际参数不是宏展开第一...

也就是说,参数##已扩展。

通过实施使用xcat宏观你解决该问题的额外的间接(A过程被称为参数预扫是跳跃的,实际上评估结果字符串两次)

+0

感谢。你能解释为什么“通过使用你正在解决问题的xcat宏实现额外的间接寻址”? – Tim

+0

如果“xcat(xcat(1,2),3)确实产生了123”,那么每个“xcat(a,b)”将首先扩展为“cat(a,b)”,然后是'a ## b'。我猜外面的'xcat'首先被扩展,接着是内部的'xcat',所以当第一次出现##时,它将阻止任何进一步的扩展,然后为什么会说“xcat(xcat ),3)产生123“? – Tim