请考虑以下设置:
啊
#define A 5 #define B A #undef A #define A 3
AC
#include "a.h" #includeint main() { printf("%d\n", B); return 0; }
虽然这非常合理地打印3,有没有办法让它打印5,即在第二行啊已经替换为5的A?
不,没有办法做到这一点.除非你知道所有可能的值A
,并且它们总是整数,在这种情况下你可以依次费力地测试每一个:
#if A == 0 # define B 0 #elif A == 1 # define B 1 #elif A == 2 # define B 2 /* ... and a very long etc. */ #endif
如果您的用例仅涉及整数,那么您有更多选择.例如,您可以声明B
为static const int
或enum
(取决于语言)而不是宏,这显然会使用宏的当前值.如果你真的真的想要宏,那么Boost预处理库就可以实现#if
上面繁琐的s 序列(有一些巧妙的做法可以减少log(N)而不是N所需的预处理器语句的数量).
#define
预处理器指令中没有宏替换; §6.10段中涵盖了这一事实.C标准中的7个(C++标准第16段第6段,措辞相同):
除非另有说明,否则预处理指令中的预处理标记不受宏扩展的影响.
在#if
和#include
指令的描述中,标准指定宏替换确实发生,这就是#if
上面的解决方案工作的原因(以及Boost实现,它也使用计算#include
).
是.Boost的预处理器库(一组可移植包含,而不是扩展的预处理器)包括对"可变"宏定义的支持.您可以将其定义为扩展为引用可变槽,而不是将宏定义为直接扩展为值,可以更改它,因为它可以提前将"已分配"值扩展到它.在这种情况下,你对改变价值的能力不太感兴趣,而不是事实上这种早期扩张意味着它可以A
在使用B
或重新定义之前的某个点上获取价值A
.
#include#define A 5 #define B BOOST_PP_SLOT(1) // "assign" A to B #define BOOST_PP_VALUE A #include BOOST_PP_ASSIGN_SLOT(1) #undef A #define A 3 #include "a.h" #include int main() { printf("%d\n", B); // 5 return 0; }
支持仅限于整数.它充分利用了事实的优点#if
的任何指示力扩展包含宏(所以做#line
和#error
,虽然这些都不是为了这个目的非常有用),并使用它们来建立一个相当于整数值的插槽被分配到,存储在隐藏后端宏.这样它就可以从中"提取"一个值A
,B
然后即使A
更改或被删除也可以引用该值本身.