C 预处理器宏扩展自身

C preprocessor macro expanding itself

我认为我的问题的答案与 C Preprocessor, Stringify the result of a macro 相关。但是,我无法将解决方案应用于我的用例。

我有这个功能:

astNodePtr createNode(int lineno, int nodeType, ...);

我有这个宏:

#define NODE(nodeType, ...) createNode(yylineno,nodeType,##__VA_ARGS__)

一切正常,直到我遇到这样一行:

NODE(1,x,NODE(2,y,z))

我的 linker 给我一个错误:undefined reference to 'NODE'

编辑:

我试过了(受上述link的启发)

#define EXPAND(x) ##x
#define NODE(nodeType, ...) createNode(yylineno,nodeType, EXPAND(__VA_ARGS__))

但是,我得到了同样的错误。

编辑:

我应该提到我也这样使用宏:NODE(5)

因此,为了避免尾随逗号问题,我需要在__VA_ARGS__前面加上##

去掉宏体中的##。那阻止了嵌套调用的扩展。 IE。尝试:

#define NODE(nodeType, ...) createNode(yylineno,nodeType,__VA_ARGS__)

更新:通过对你的问题的编辑,我现在明白了需要 对于宏中的 ##。 Chris Dodd 的解决方案解决了这个问题 问题很好

这是另一种方法。该解决方案增加了一层扩展 它在顶层处理嵌套的宏,然后解决 较低级别的尾随逗号问题:

#define NODE2(nodeType, ...) createNode(yylineno,nodeType,##__VA_ARGS__)
#define NODE(...) NODE2(__VA_ARGS__)

这会根据需要处理以下示例案例,没有尾随 逗号:

NODE(a,NODE(b,c))
NODE(x)
NODE(NODE(y))

这种方法的优点是它更通用。 特别是,即使没有强制性,它也会起作用 nodeType 争论。例如,如果名称更改为 FOO 并且 nodeType 参数已消除,以下将起作用:

#define FOO2(...) createNode(yylineno,##__VA_ARGS__)
#define FOO(...) FOO2(__VA_ARGS__)

这处理以下示例案例,没有尾随逗号:

FOO(FOO(b))
FOO()
FOO(FOO())

其实你只需要

#define NODE(...) createNode(yylineno, __VA_ARGS__)

问题是使用 ## 也会阻止在替换之前扩展 __VA_ARGS__ 参数中的宏,而且,虽然宏可以在替换后扩展,但它们不能递归扩展, 所以如果你想在另一个 NODE 宏的参数中有一个 NODE 宏,你不能使用 ##。幸运的是,在你的情况下,你可以避免需要 ## 通过始终至少有一个参数来摆脱没有额外参数的 NODE 调用中的尾随逗号(无论如何这是一个非标准的 gcc 扩展) ... -- nodeType 参数。