Reputation: 141554
I have a debugging setup where you set various debug flags in the makefile, and then in each source file we have:
#ifdef DEBUG_FLAG
# define DEBUGGING(...) Something(__VA_ARGS__)
#else
# define DEBUGGING(...) do {} while(0)
#endif
I would like to make this be more concise by having the source file say something like:
#define DEBUGGING(...) DEBUG_HELP( DEBUG_FLAG, Something(__VA_ARGS__) )
where DEBUG_HELP
is defined in a header, with the same end result, i.e. using the DEBUGGING
macro will cause Something
to be called, only if DEBUG_FLAG
was defined as non-zero. If DEBUG_FLAG
was not defined at all then the code should still compile, just not call Something
.
Is this possible at all?
My attempts so far, I have not been able to figure out a way to not get a compilation error in the case where DEBUG_FLAG
was not defined at all.
Upvotes: 2
Views: 1055
Reputation: 9962
Stealing from Nominal Animal's answer to a similar question, Test if preprocessor symbol is defined inside macro, the following should work. If foo.c
is:
#define STRINGIFY(x) #x
#define DEBUG_HELP(flag, action) \
do { \
if (strcmp(STRINGIFY(flag), #flag)) && \
strcmp(STRINGIFY(flag), "0")) { \
action; \
} \
} while (0)
#define DEBUGGING(...) DEBUG_HELP(DEBUG_FLAG, printf(__VA_ARGS__))
DEBUGGING("%d\n", 42);
then:
$ gcc -E -P foo.c
do { if (strcmp("DEBUG_FLAG", "DEBUG_FLAG")) && strcmp("DEBUG_FLAG", "0")) { printf("%d\n", 42); } } while (0);
$ gcc -E -P foo.c -DDEBUG_FLAG=0
do { if (strcmp("0", "DEBUG_FLAG")) && strcmp("0", "0")) { printf("%d\n", 42); } } while (0);
$ gcc -E -P foo.c -DDEBUG_FLAG
do { if (strcmp("1", "DEBUG_FLAG")) && strcmp("1", "0")) { printf("%d\n", 42); } } while (0);
$ gcc -E -P foo.c -DDEBUG_FLAG=bar
do { if (strcmp("bar", "DEBUG_FLAG")) && strcmp("bar", "0")) { printf("%d\n", 42); } } while (0);
So with DEBUG_FLAG
undefined or set to 0
, the if
condition will be false. And if DEBUG_FLAG
is anything else, with one exception, the condition will be true. The one exception is when you have:
#define DEBUG_FLAG DEBUG_FLAG
The strcmp
should all be evaluated at compile-time with gcc, Clang, and MSVC, although I cannot find any guarantee. As a test, see the following code:
#include <string.h>
int main(void) {
if (strcmp("foo", "foo"))
return 888;
if (&"foo" != &"foo") // '&' for Clang
return 999;
return 777;
}
compiled here at https://godbolt.org/g/2kVShr.
Upvotes: 2
Reputation: 16043
You could have the condition in separate header file.
debug_help.h
#ifdef DEBUG_FLAG
#define DEBUG_HELP(...) __VA_ARGS__
#else
#define DEBUG_HELP(...) do {} while(0)
#endif
some_source_module.c
#include "debug_help.h"
#define DEBUGGING(...) DEBUG_HELP(puts(__VA_ARGS__))
DEBUGGING("test"); // expands to puts("test"); when DEBUG_FLAG is defined
You could omit the #include "debug_help.h"
if you can have compiler auto-include it for each compilation unit.
Upvotes: 0