这个宏展开为什么会work?

现在有一组宏,能够在预处理阶段检测某个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,是我对展开的哪一步理解有误吗?

阅读 691
1 个回答

不是先替换参数,再展开外层宏。(虽然这样叙述容易理解,而且大部分情况下也没错)

是再替换外层宏的同时,用于替换宏参数的内容是参数宏展开的结果。

所以:

#define MUX_WITH_COMMA(contain_comma, a, b) CHOOSE2nd(contain_comma a, b)
对以下调用:
MUX_WITH_COMMA(concat(__P_DEF_, 1), a, b)
               ~~~~~~~~~~~~~~~~~~~
               展开为 __P_DEF_1
               继续展开为 X,

所以展开结果(CHOOSE2nd(conatin_comma a,b))中的 contain_comma 被替换为 X,。最终结果为:

CHOOSE2nd(conatin_comma a, b)
          ~~~~~~~~~~~~~
CHOOSE2nd(X,            a, b)
          ~~~~~~~~~~~~~
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏