使用#define -d列表作为C预处理器宏的输入

时间:2012-04-24 21:17:08

标签: c macros c-preprocessor

在一个示例项目中,我定义了宏

#define FOO(x, y) x + y   .

这非常有效。例如,FOO(42, 1337)评估为1379

但是,我现在想要使用另一个#define

#define SAMPLE 42, 1337

当我现在拨打FOO(SAMPLE)时,这不起作用。编译器告诉我FOO接受两个参数,但只用一个参数调用。

我猜其原因在于,虽然宏的参数是在函数本身之前进行计算的,但预处理器在此评估之后不会再次解析整个指令。这类似于无法从宏输出其他预处理程序指令的事实。

是否有可能获得所需的功能?

不可能用C函数替换FOO宏。原始宏位于我无法更改的第三方代码中,它输出以逗号分隔的值列表,以便直接在数组初始值设定项中使用。因此,C函数不能复制相同的行为。

如果无法通过简单的方法完成此任务:您如何以可维护的形式存储(x, y)对?就我而言,有8个论点。因此,将各个部分存储在单独的#define - s中也不容易维护。

1 个答案:

答案 0 :(得分:4)

您遇到的问题是预处理器不匹配并按您想要的顺序展开宏。现在你通常可以通过插入一些额外的宏来强制它获得正确的顺序,从而做到你想做的事情,但为此你需要了解正常的顺序是什么。

  • 当编译器看到带有参数后跟(的宏的名称时,它首先扫描该参数列表,将其分解为参数而不识别或扩展参数中的任何宏。

  • 解析并分离参数后,然后重新扫描宏的每个参数,并扩展任何使用参数找到的参数UNLESS参数与宏体中的###一起使用

  • 然后用(现在可能扩展的)参数替换正文中的每个参数实例

  • 最后,它会重新扫描正文中可能存在的任何其他宏以进行扩展。在这一次扫描中,原始宏将无法识别并重新展开,因此您无法进行递归宏扩展

因此,您可以通过小心使用EXPAND宏来获得所需的效果,该宏采用单个参数并对其进行扩展,从而允许您在流程的正确位置强制进行额外的扩展:

#define EXPAND(X)   X
#define FOO(x,y)    x + y
#define SAMPLE      42, 1337

EXPAND(FOO EXPAND((SAMPLE)))

在这种情况下,您首先在参数列表中显式展开宏,然后手动展开生成的宏调用。

按问题海报更新

#define INVOKE(macro, ...) macro(__VA_ARGS__)

INVOKE(FOO, SAMPLE)

提供了一个扩展的解决方案,可以在不使用EXPAND s。

的代码混乱的情况下工作