I would like to write code in C something like this:
if(defined(MACRO)) ... else ...
but I could not find any way to do this in C, since the defined(MACRO) preprocessor operator works only inside #if's. Is there a way to do this?
What I really like to do is to write:
ASSERT(UART, var >= 0);
where
#define ASSERT(NAME, TEST) \
do { \
if (defined(NAME) && !(TEST)) \
printf("Assert failed"); \
} while(0)
thus I could turn on ASSERT checks when a macro is defined and if it is not defined, then the asserts should not be checked. If you try to do this, then you get:
implicit declaration of function `defined'
which is quite understandable since the GCC compiler does not find the defined() preprocessor operator.
A macro by comex is expanded to 1 if the argument is defined to 1. Otherwise it is expanded to 0:
#define is_set(macro) is_set_(macro)
#define macrotest_1 ,
#define is_set_(value) is_set__(macrotest_##value)
#define is_set__(comma) is_set___(comma 1, 0)
#define is_set___(_, v, ...) v
You can use it as follows:
if (is_set(MACRO)) {
/* Do something when MACRO is set */
}
Explanation:
The trick is based on variadic function-like macros (...) and preprocessor token concatenation (##).
is_set is simply a wrapper to facilitate the expansion of its parameter.is_set_ tries to concatenate macrotest_ with the evaluated value of its input (comma).
If its input is defined, then this works; otherwise is_set__ is called with macrotest_<macro> where <macro> is the original argument to is_set (e.g., is_set(foo) leads to macrotest_foo if foo is not a defined macro).
In is_set__ its parameter is again expanded but this only works out if it is passed macrotest_1.
If it is, then is_set___(, 1, 0) is called because comma evaluates to , (note the 3 parameters!).
For any other value of comma (i.e., if the macro to be tested is undefined or has any other (expanded) value than 1 the parameter can not be expanded and thus is_set___(macrotest_<macro> 1, 0) is called, which has only 2 arguments.
Eventually, is_set___ simply selects its second parameter for its "output" and drops everything else.
Due to the behavior of is_set__ this leads to either 1 if the macro to be tested is defined and 1, or 0 otherwise.
Ok, based on the previous post I got this idea, which seems to work:
#define DEFINEDX(NAME) ((#NAME)[0] == 0) #define DEFINED(NAME) DEFINEDX(NAME)
This will check if NAME is defined and therefore it expands to the empty string with 0 at its first character, or it is undefined in which case it is not the empty string. This works with GCC, so one can write
if( DEFINED(MACRO) ) ...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With