C中使用宏测试特定宏是否被定义

ref
起因: 在阅读ics-pa代码macro.h中发现这样一个需求:如何在宏中测试特定宏是否被定义

#define str_temp(x) #x
#define str(x) str_temp(x)

// strlen() for string constant
#define STRLEN(CONST_STR) (sizeof(CONST_STR) - 1)

// calculate the length of an array
#define ARRLEN(arr) (int)(sizeof(arr) / sizeof(arr[0]))

// macro concatenation
#define concat_temp(x, y) x ## y
#define concat(x, y) concat_temp(x, y)
#define concat3(x, y, z) concat(concat(x, y), z)
#define concat4(x, y, z, w) concat3(concat(x, y), z, w)
#define concat5(x, y, z, v, w) concat4(concat(x, y), z, v, w)

// 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 __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)

// test if a boolean macro is defined
#define ISDEF(macro) MUXDEF(macro, 1, 0)
// test if a boolean macro is undefined
#define ISNDEF(macro) MUXNDEF(macro, 1, 0)
// test if a boolean macro is defined to 1
#define ISONE(macro) MUXONE(macro, 1, 0)
// test if a boolean macro is defined to 0
#define ISZERO(macro) MUXZERO(macro, 1, 0)
// test if a macro of ANY type is defined
// NOTE1: it ONLY works inside a function, since it calls `strcmp()`
// NOTE2: macros defined to themselves (#define A A) will get wrong results
#define isdef(macro) (strcmp("" #macro, "" str(macro)) != 0)

#x 代表将x展开为一个字符串量,"" #x 将x展开为一个字符串量,以ISDEF(macro)为例:
macro是一个宏,其值为0或1
ISDEF 变为MUXDEF(macro,1,0)再变为
MUX_MACRO_PROPERTY(__P_DEF_, macro, 1, 0)变为MUX_WITH_COMMA(concat(p, macro), 1, 0)
实际上就是__P_DEF_0或者__P_DEF_1,这二者都转义成X, 即MUX_WITH_COMMA(X,,1, 0)即CHOOSE2nd(X,1,0)
但若macro未定义为0或者1,则concat(p,macro)不会被转义X, 即__P_DEF_macro 则变为CHOOSE2nd(__P_DEF_1,0) 选择为1
HELLO宏未定义

int x = MUXDEF(HELLO, 1, 0) ;
int x = MUX_MACRO_PROPERTY(__P_DEF_, HELLO, 1, 0) ;
int x = MUX_WITH_COMMA(__P_DEF_HELLO, 1, 0) ;
int x = CHOOSE2nd(__P_DEF_HELLO 1, 0) ;
int x = 0;

HELLO宏定义后:

int x = MUXDEF(1, 1, 0) ;
int x = MUX_MACRO_PROPERTY(__P_DEF_, 1, 1, 0) ;
int x = MUX_WITH_COMMA(X,, 1, 0) ;
int x = CHOOSE2nd(X, 1, 0) ;

版权声明:
作者:carott
链接:https://blog.hellholestudios.top/archives/1572
来源:Hell Hole Studios Blog
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
< <上一篇
下一篇>>
文章目录
关闭
目 录