考虑以下代码:
#define N_ 0
#define N_X 1
#define M(a) N_
M(arg)X; // #1 -- I'd like this to expand to N_X, and ultimately 1; but it's 0X instead
M(arg); // #2 -- this should and does expand to 0
#1的问题是,在扩展M()之后,结果包含N_,在
答案 0 :(得分:8)
首先,N_ X
和N_X
之间存在差异。第一个是两个令牌。要形成一个令牌,您必须使用令牌粘贴运算符##
,但此运算符禁止宏扩展,因此:
M(a) ## X //Compiler error can't paste ')' and X
导致编译错误,因为它尝试粘贴M(a)
而不是N_
。您可以通过使用额外级别的宏(这是非常常用的宏)允许宏在粘贴之前展开:
#define PRIMITIVE_CAT(x, y) x ## y
#define CAT(x, y) PRIMITIVE_CAT(x, y)
但是,在您的情况下,这仍然无效:
CAT(M(a), X) //expands to 0
这是因为,您使用的是对象宏,而不是函数宏。如果将其更改为功能宏,它将按您的需要工作:
#define N_() 0
#define N_X() 1
#define M(a) N_
CAT(M(arg), X)() // expands to 1
M(arg)() // expands to 0
功能宏功能更强大,您可以延迟它们的扩展。以下是如何将它们延迟一次扫描:
#define EMPTY()
#define DEFER(x) x EMPTY()
N_() //Expands to 0
DEFER(N_)() //Expands N_ ()
像这样延迟宏扩展是在预处理器中实现递归的方法之一。
答案 1 :(得分:1)
没有。预处理器逐行工作,不执行任何递归或回溯。它读取一行,处理特殊的#
行或替换某些行,然后转到下一行。这也意味着它不会在#define
之前或#undef
之后进行任何替换。你必须解决这个问题。