【问题标题】:Recursive C macro not expanded递归 C 宏未扩展
【发布时间】:2016-07-28 15:10:45
【问题描述】:

我正在研究一个递归宏。但是,它似乎没有递归扩展。这是一个最小的工作示例来说明我的意思:

// ignore input, do nothing
#define ignore(...)
// choose between 6 names, depending on arity
#define choose(_1,_2,_3,_4,_5,_6,NAME,...) NAME
// if more than one parameter is given to this macro, then execute f, otherwise ignore
#define ifMore(f,...) choose(__VA_ARGS__,f,f,f,f,f,ignore)(__VA_ARGS__)
// call recursively if there are more parameters
#define recursive(first,args...) first:ifMore(recursive,args)

recursive(a,b,c,d)
// should print: a:b:c:d
// prints: a:recursive(b,c,d)

recursive 宏应递归扩展自身并始终连接结果,用冒号分隔。但是,它不起作用。递归宏生成正确(从结果a:recursive(b,c,d) 可以看出,其中再次包含对宏的格式良好的调用),但生成的递归调用未扩展。

为什么会这样,我怎样才能得到我想要的行为?

【问题讨论】:

  • '我正在研究一个递归宏' - 好吧,很难知道该说什么:(非递归宏是一个 PITA。

标签: c macros c-preprocessor


【解决方案1】:

你无法得到你想要的行为。根据设计,C 预处理器不是图灵完备的。

您可以使用多个宏来获得多个替换,但使用任意数量的替换将无法实现真正​​的递归。

【讨论】:

  • 什么规则阻止我的宏在这里再次展开?规则是什么?
【解决方案2】:

正如其他人所提到的,纯递归是不可能使用 C 宏的。但是,可以模拟类似递归的效果。

Boost Pre-Processor 工具在 C 和 C++ 中都能很好地做到这一点,并且是一个独立的库:

http://www.boost.org/doc/libs/1_60_0/libs/preprocessor/doc/index.html

【讨论】:

  • 对递归级别的数量有硬编码限制。 (256,IIRC)
【解决方案3】:

编译器预处理器不会重新扩展您定义的宏。也就是说,它将盲目地将在宏语句中找到的任何字符串替换为在定义中找到的字符串。例如,Can we have recursive macros?Macro recursive expansion to a sequenceC preprocessor, recursive macros

也就是说,recursive(a,b,c,d) 将扩展为a:recursive(b,c,d),然后预处理器将继续执行基本代码中的下一行。它不会循环尝试继续扩展字符串(请参阅我引用的链接)。

【讨论】:

  • “它将盲目地将宏语句中找到的任何字符串替换为它在定义中找到的字符串”。嗯,这正是我想要的。但是这里不行!结果中明显有字符串recursive(b,c,d),但没有替换为recursive定义中的字符串。
  • 不,关键是您的定义包含字符串recursive(b, c, d),因此它会盲目地将该字符串复制到要编译的代码中。按照我显示的链接。
  • @sabbahillel:但是如果主体包含不同的宏,它会扩展它。所以它与“盲目复制”无关。事实上,预处理器已经睁大了眼睛。它正在寻找要扩展的宏,但会小心地忽略已经扩展的宏。
猜你喜欢
  • 2013-12-09
  • 1970-01-01
  • 2010-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多