gpt4 book ai didi

C 宏扩展不像预期的那样递归

转载 作者:行者123 更新时间:2023-12-04 01:13:17 25 4
gpt4 key购买 nike

#define EVAL1(...) __VA_ARGS__
#define RECURSE() I am recursive, look: _RECURSE()()
#define _RECURSE() RECURSE

I expected:
EVAL1(RECURSE())
=> EVAL1(I am recursive, look: _RECURSE()())
=> EVAL1(I am recursive, look: RECURSE())
=> I am recursive, look: RECURSE()
=> I am recursive, look:I am recursive, look: _RECURSE()()

what I got:
EVAL1(RECURSE())
=> I am recursive, look: RECURSE()

为什么 RECURSE() 在作为参数传递给 EVAL1 时没有第二次展开?

另一种实现我想要的方法是:

#define EVAL1(...) __VA_ARGS__
#define EMPTY()
#define DEFER1(m) m EMPTY()
#define RECURSE() I am recursive, look: DEFER1(_RECURSE)()()
#define _RECURSE() RECURSE

EVAL1(RECURSE())
=> I am recursive, look: I am recursive, look: _RECURSE ()()

但我不确定为什么会这样。

最佳答案

C 预处理器不允许递归。更准确地说,当预处理器扩展宏时,它会记住正在扩展的宏。如果它找到当前正在展开的宏之一,它会保持不变。

在您的示例中,评估链是:

  • EVAL1(RECURSE())
  • 扩展 EVAL1:RECURSE()
  • 扩展EVAL1RECURSE:我是递归的,看:_RECURSE()()
  • 扩展EVAL1, _RECURSE, RECURSE: 我是递归的,看:RECURSE()
  • 没有什么可以扩展的了,完成了。

禁止递归使您可以使用同名的宏来包装函数。例如:

#define foo(x, y) (printf("DEBUG: foo was called in %s at line %d\n", __FILE__, __LINE__), foo(x, y))

禁止递归也保证编译会终止。 (这实际上不是真的:您可以通过 #include 指令获得无限递归。但它比简单的递归 #define 需要更多的工作。终止并不一定意味着快速终止:可以构建仅在很长时间后终止的预处理器扩展。)

关于C 宏扩展不像预期的那样递归,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64135935/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com