2

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.

3
  • Is there a restriction on how or where DEBUG_HELP is defined? Can it be wrapped in #ifdef DEBUG_FLAG condition? Commented Aug 25, 2017 at 9:09
  • Perhaps I'm missing something here but why can't you simply do #if DEBUG_FLAG #define DEBUGGING(...) Something(__VA_ARGS__) #endif ? Commented Aug 25, 2017 at 11:40
  • 1
    Possible duplicate of Test if preprocessor symbol is defined inside macro Commented Aug 25, 2017 at 22:35

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

Comments

0

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.