我相信我的问题的答案与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))
我的链接器给我一个错误:undefined reference to 'NODE'
编辑:
我已经尝试过(受上述链接的启发)
#define EXPAND(x) ##x
#define NODE(nodeType, ...) createNode(yylineno,nodeType, EXPAND(__VA_ARGS__))
但是,我遇到了同样的错误。
编辑:
我应该提到,我也因此使用了宏:NODE(5)
因此,为了避免尾随逗号问题,我需要在##
前面加上__VA_ARGS__
。
答案 0 :(得分:3)
摆脱宏主体中的##
。这阻碍了嵌套调用的扩展。即尝试:
#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())
答案 1 :(得分:2)
您实际上只需要
#define NODE(...) createNode(yylineno, __VA_ARGS__)
问题在于,使用##
还会阻止替换前__VA_ARGS__
参数中宏的扩展,并且尽管宏可以在替换后被扩展,但是它们不能递归扩展,因此如果要在另一个NODE
宏的参数中包含NODE
宏,则不能使用##
。幸运的是,您可以避免##
摆脱NODE调用中尾随逗号的需要,而不必使用额外的参数(无论如何这都是非标准的gcc扩展名),方法是始终为该参数至少使用一个...
-nodeType
参数。