【问题标题】:C preprocessor macro expanding itselfC 预处理器宏扩展自身
【发布时间】:2020-10-18 10:57:10
【问题描述】:

我相信我的问题的答案与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__ 前面加上## 以避免尾随逗号问题。

【问题讨论】:

  • 另见C11标准n1570Modern C这本书,在Bismon的源代码中寻找灵感
  • 你希望展开的结果是什么?
  • createNode(yylineno,1,x,createNode(yylineno,2,y,z))

标签: c gcc c-preprocessor


【解决方案1】:

去掉宏体内的##。这阻止了嵌套调用的扩展。 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())

【讨论】:

  • gcc documentation 表示,如果我没看错的话,我需要## 来解决尾随逗号问题。
  • @DanielWalker 感谢您澄清您遇到的问题。我现在了解您的宏中需要##。我已经更新了我的答案以提供该问题的一般解决方案。请注意,此方法不依赖于强制 nodeType 参数。
【解决方案2】:

其实你只需要

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

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

【讨论】:

  • gcc documentation 说,如果我没看错的话,我需要## 来解决尾随逗号问题。
  • 您的示例中没有任何只有一个参数的 NODE 调用,因此您不需要处理尾随逗号,但您可以通过将第一个参数吸收到...
  • 我在其他地方也有类似的电话。即NODE(5);
猜你喜欢
  • 2018-01-04
  • 1970-01-01
  • 1970-01-01
  • 2020-09-18
  • 2014-04-17
  • 1970-01-01
  • 2021-06-10
  • 1970-01-01
相关资源
最近更新 更多