在一个示例项目中,我定义了宏
#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中也不容易维护。
答案 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。