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