现在有一组宏,能够在预处理阶段检测某个bool宏是否被定义,并且根据被检测的宏是否被定义来选择不同的值,这组宏的定义如下:
// macro concatenation
#define concat_temp(x, y) x ## y
#define concat(x, y) concat_temp(x, y)
// macro testing
#define CHOOSE2nd(a, b, ...) b
#define MUX_WITH_COMMA(contain_comma, a, b) CHOOSE2nd(contain_comma a, b)
#define MUX_MACRO_PROPERTY(p, macro, a, b) MUX_WITH_COMMA(concat(p, macro), a, b)
// define placeholders for some property
#define __P_DEF_0 X,
#define __P_DEF_1 X,
#define __P_ONE_1 X,
#define __P_ZERO_0 X,
// define some selection functions based on the properties of BOOLEAN macro
#define MUXDEF(macro, X, Y) MUX_MACRO_PROPERTY(__P_DEF_, macro, X, Y)
#define MUXNDEF(macro, X, Y) MUX_MACRO_PROPERTY(__P_DEF_, macro, Y, X)
#define MUXONE(macro, X, Y) MUX_MACRO_PROPERTY(__P_ONE_, macro, X, Y)
#define MUXZERO(macro, X, Y) MUX_MACRO_PROPERTY(__P_ZERO_,macro, X, Y)
但是,按照宏的展开顺序,如果在扫描的过程之中,发现宏的参数之中包含其他宏,那么首先会对参数之中的宏进行展开,随后才会展开宏本身。
所以,对于形如MUXDEF(test, 0, 1) 的展开,应当如下:
#define test 1
int i = MUDXDEF(test, 0, 1);
// MUXDEF(test, 0, 1) -> MUXDEF(1, 0, 1) ->
// MUX_MACRO_PROPERTY(__P_ZDEF_, 1, X, Y) ->
// MUX_WITH_COMMA(concat(__P_DEF_, 1), a, b) MUX_WITH_COMMA(__P_DEF_1, a, b) ->
// MUX_WITH_COMMA(X,, a, b) ->
// CHOOSE2nd(X,,a,b) ->
理论上是展开的结果为空,但是实际展开的结果是0,是我对展开的哪一步理解有误吗?
不是先替换参数,再展开外层宏。(虽然这样叙述容易理解,而且大部分情况下也没错)
是再替换外层宏的同时,用于替换宏参数的内容是参数宏展开的结果。
所以:
所以展开结果(
CHOOSE2nd(conatin_comma a,b)
)中的 contain_comma 被替换为X,
。最终结果为: