Zephyr的IS_ENABLED

Creative Commons
本作品采用知识共享署名

本文说明zephyr中IS_ENABLED的原理。

概述

zephyr里面有一个有意思的宏IS_ENABLED用于判断某个宏是否被定义,这里分析IS_ENABLED的实现方法,以了解其使用的局限性。

分析

宏定义代码如下:

1
2
3
4
5
#define IS_ENABLED(config_macro) _IS_ENABLED1(config_macro)
#define _IS_ENABLED1(config_macro) _IS_ENABLED2(_XXXX##config_macro)
#define _XXXX1 _YYYY,
#define _IS_ENABLED2(one_or_two_args) _IS_ENABLED3(one_or_two_args true, false)
#define _IS_ENABLED3(ignore_this, val, ...) val

enable实例

1
2
3
4
5
6
7
8
9
#define CONFIG_SHELL_VT100_COLORS 1
IS_ENABLED(CONFIG_SHELL_VT100_COLORS)
上面等价于
IS_ENABLED(1)
_IS_ENABLED1(1)
_IS_ENABLED2(_XXXX1)
_IS_ENABLED2(_YYYY,) // **这里是重点#define _XXXX1 _YYYY, 只有_XXXX1能变为_YYYY,**
_IS_ENABLED3(_YYYY, true, false) // ** 这里才会有3个参数,让true变为_IS_ENABLED3的val **
true

最后 IS_ENABLED(CONFIG_SHELL_VT100_COLORS) 等价于 ture

disable实例

1
2
3
4
5
6
7
8
#define CONFIG_SHELL_VT100_COLORS 0
IS_ENABLED(CONFIG_SHELL_VT100_COLORS)
上面等价于
IS_ENABLED(0)
_IS_ENABLED1(0)
_IS_ENABLED2(_XXXX0)
_IS_ENABLED3(_XXXX0 true, false)
false

其它值

1
2
3
4
5
6
7
8
#define CONFIG_SHELL_VT100_COLORS 0
IS_ENABLED(CONFIG_SHELL_VT100_COLORS)
上面等价于
IS_ENABLED(3)
_IS_ENABLED1(3)
_IS_ENABLED2(_XXXX3)
_IS_ENABLED3(_XXXX3 true, false)
false

未定义

1
2
3
4
5
6
7
IS_ENABLED(CONFIG_SHELL_VT100_COLORS)
上面等价于
IS_ENABLED(CONFIG_SHELL_VT100_COLORS)
_IS_ENABLED1(CONFIG_SHELL_VT100_COLORS)
_IS_ENABLED2(_XXXXCONFIG_SHELL_VT100_COLORS)
_IS_ENABLED3(_XXXXCONFIG_SHELL_VT100_COLORS true, false)
false

结论

从前面看,只有当判断的宏被定义为1才会转换为true,其它情况全是false。使用时应注意该局限。
从zephyr的代码看,IS_ENABLED只会用于bool型的CONFIG_XXX,也就是只能选择y,n的config。