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
参数。
我认为我的问题的答案与 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
参数。