It is a pity that the defined operator is available only in the context of #if and #ifelse , but not for macro extensions. Be that as it may, I agree with the rice about the decisions of various ugliness.
This requires a solution that requires certain values ββto be surrounded by parentheses. Then you can use the identifier as a regular value, and you can also pass it to DEF , which will expand to 1 if the macro is in parentheses, or 0 if not. (This is the trick I learned here .)
Using the DEF macro, you can create helper macros that extend or ignore this definition:
#define M_CHECK(...) M_CHECK_(__VA_ARGS__) #define M_CHECK_(a, b, ...) b #define M_IS_PAREN(x) M_CHECK(M_IS_PAREN_ x, 0) #define M_IS_PAREN_(...) 1, 1 #define M_CONCAT(a, b) M_CONCAT_(a, b) #define M_CONCAT_(a, b) a ## b #define DEF(x) M_IS_PAREN(x) #define DEF_IF_0(id, def) #define DEF_IF_1(id, def) {id, def}, #define COND_DEF(x, y) M_CONCAT(DEF_IF_, DEF(x))(x, y) #define ID_1 (27) #define ID_3 (28) #define ID_4 (29) static const MyTypedef_t MyList[] = { COND_DEF(ID_1, 1) COND_DEF(ID_2, 2) COND_DEF(ID_3, 3) COND_DEF(ID_4, 4) COND_DEF(ID_5, 5) };
This will give:
static const MyTypedef_t MyList[] = { {(27), 1}, {(28), 3}, {(29), 4}, };
You can also use the DEF macro in code that will be expanded to 0 or 1:
printf("ID_1 is %s.\n", DEF(ID_1) ? "defined" : "undefined");