神奇的宏定义

阅读某项目时,遇到了以下两个神奇的宏用法

IFDEF(CONFIG_DEVICE, init_device());
MUXDEF(CONFIG_TRACE, "ON", "OFF")

顾名思义,第一个的意思就是如果定义了CONFIG_DEVICE宏才执行后面的函数调用,第二个的含义则是如果定义了CONFIG_TRACE宏则为"ON",否则为"OFF"

大家可以思考思考,这样的宏你们会怎么实现呢?
Hint:并不简单哦,会用到不少宏定义的技巧。(如果你有简单的方法请一定留言告诉我!)

点击查看解答
// macro concatenation
#define concat_temp(x, y) x ## y
#define concat(x, y) concat_temp(x, y)

// macro testing
// See https://stackoverflow.com/questions/26099745/test-if-preprocessor-symbol-is-defined-inside-macro
#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 some selection functions based on the properties of BOOLEAN macro
#define MUXDEF(macro, X, Y)  MUX_MACRO_PROPERTY(__P_DEF_, macro, X, Y)

// simplification for conditional compilation
#define __IGNORE(...)
#define __KEEP(...) __VA_ARGS__

// keep the code if a boolean macro is defined
#define IFDEF(macro, ...) MUXDEF(macro, __KEEP, __IGNORE)(__VA_ARGS__)

解释每一个宏很枯燥,不如让做一个人形预处理器,直接针对第一个宏用法对其进行展开(第二个宏的用法包含在第一个之中)

// For CONFIG_DEVICE not defined
IFDEF(CONFIG_DEVICE, init_device());
MUXDEF(CONFIG_DEVICE, __KEEP, __INGORE)(init_device());
MUX_MACRO_PROPERTY(__P_DEF_, CONFIG_DEVICE, __KEEP, __INGORE)(init_device());
MUX_WITH_COMMA(concat(__P_DEF_, CONFIG_DEVICE), __KEEP, __INGORE)(init_device());
MUX_WITH_COMMA(__P_DEF_CONFIG_DEVICE, __KEEP, __INGORE)(init_device());
CHOOSE2nd(__P_DEF_CONFIG_DEVICE __KEEP, __INGORE)(init_device());

注意以上展开过程保留了CONFIG_DEVICE,如果其定义为1或0,则继续展开可以得到

CHOOSE2nd(X, __KEEP, __INGORE)(init_device());
__KEEP(init_device());
init_device();

如果其没有定义则该语句直接变成了一条空语句。

怎么样是不是很神奇呢?

原文链接:https://www.cnblogs.com/zhangyi1357/p/16192431.html
转载请注明出处!

posted @ 2022-04-25 22:41  zhangyi1357  阅读(717)  评论(1编辑  收藏  举报