递归C宏未展开

递归C宏未展开,c,macros,c-preprocessor,C,Macros,C Preprocessor,我正在处理一个递归宏。然而,它似乎不是递归展开的。下面是一个简单的工作示例来说明我的意思: // 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 exe

我正在处理一个递归宏。然而,它似乎不是递归展开的。下面是一个简单的工作示例来说明我的意思:

// 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)
中所示,其中再次包含对宏的格式良好的调用),但生成的递归调用未被取消


为什么会出现这种情况?我怎样才能得到我想要的行为?

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


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

编译器预处理器不会重新展开您定义的宏。也就是说,它将盲目地将在宏语句中找到的任何字符串替换为在定义中找到的字符串。例如,或


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

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

Boost预处理器工具对C和C++都很好,是一个独立的库:


“我正在处理递归宏”-很难知道该怎么说:(非递归宏是PITA。什么规则阻止我的宏在这里再次扩展?规则是什么?“它会盲目地用定义中找到的字符串替换宏语句中找到的任何字符串”。这正是我想要的。但它在这里不起作用!结果中显然有字符串
递归(b,c,d)
,但在
递归
的定义中它没有替换为字符串。关键是你的定义包括字符串
递归(b,c,d)
因此,它会盲目地将该字符串复制到要编译的代码中。请按照我显示的链接进行操作。@sabbahillel:但如果正文包含不同的宏,它会将其展开。因此,它与“盲目复制”无关.事实上,预处理器的眼睛一直睁得大大的;它正在寻找要扩展的宏,但仔细地忽略了已经扩展的宏。对递归级别的数量有一个硬编码限制。(256,IIRC)