John
John

Reputation: 381

Debug Print Macro in C?

in C, what is the proper way to define a printf like macro that will print only when DEBUG symbol is defined?

#ifdef DEBUG
#define DEBUG_PRINT(???) ???
#else
#define DEBUG_PRINT(???) ???
#endif

where ??? is where I am not sure what to fill in

Upvotes: 38

Views: 90987

Answers (8)

Gabriel Staples
Gabriel Staples

Reputation: 53245

This works in both C and C++! (Note that the space before __VA_ARGS__ is required for it to work in C++!)

I see some minor errors in the implementation in the main answer. So, here is my approach:

#ifdef DEBUG
    #define DEBUG_PRINTF(...) printf("DEBUG: " __VA_ARGS__)
#else
    #define DEBUG_PRINTF(...) do {} while (0)
#endif

Example usage:

DEBUG_PRINTF("hello\n");

Then, if I build and run with the -DDEBUG define on in my C build options, like this:

# Build
gcc -Wall -Wextra -Werror -std=c11 -DDEBUG -o build/my_program \
my_program_tests.c my_program.c

# Run
build/my_program

then I see this output:

DEBUG: hello

But if I build withOUT the -DDEBUG define in my compiler C options, then I see no debug prints whatsoever.

See also

  1. My more generic "do anything" and "run any lines or code" approach: Generic debugging macros to conditionally compile and run any code in C or C++ based on debug levels

Other references

  1. The fix to make this compatible with C++ too: https://stackoverflow.com/a/72777133/4561887: add a space before __VA_ARGS__. Use "DEBUG: " __VA_ARGS__ instead of "DEBUG: "__VA_ARGS__!

Upvotes: 1

moonshadow
moonshadow

Reputation: 89185

#ifdef DEBUG
#define DEBUG_PRINT(...) fprintf( stderr, __VA_ARGS__ )
#else
#define DEBUG_PRINT(...) do{ } while ( 0 )
#endif

Upvotes: 31

Justin Torre
Justin Torre

Reputation: 135

I like this way the best because it wont add any asm instructions to your release build.

#define DEBUG
#ifdef DEBUG
#define  debug_printf(fmt, ...)  printf(fmt, __VA_ARGS__);
#else
#define debug_printf(fmt, ...)    /* Do nothing */
#endif

Upvotes: 0

Tom Kuschel
Tom Kuschel

Reputation: 775

Thank you mipadi, I improved your DEBUG_PRINT with file information too.

#define DEBUG 3

#if defined(DEBUG) && DEBUG > 0
 #define DEBUG_PRINT(fmt, args...) fprintf(stderr, "DEBUG: %s:%d:%s(): " fmt, \
    __FILE__, __LINE__, __func__, ##args)
#else
 #define DEBUG_PRINT(fmt, args...) /* Don't do anything in release builds */
#endif

Tested with latest clang, e.g.

int main(int argc, char **args) {
    DEBUG_PRINT("Debugging is enabled.\n");    
    DEBUG_PRINT("Debug level: %d", (int) DEBUG);
}

outputs:

DEBUG: debug.c:13:main(): Debugging is enabled.
DEBUG: debug.c:14:main(): Debug level: 3

Upvotes: 25

Sérgio
Sérgio

Reputation: 169

Use different signatures of DEBUG_PRINT, they don't have to be the same, like:

#ifdef DEBUG
#define DEBUG_PRINT printf
#else
#define DEBUG_PRINT(...)
#endif

this way on debug mode the DEBUG_PRINT call will be replaced with printf. On release it will ignore all arguments used previously.

Hope it helps.

Upvotes: 6

Sorin
Sorin

Reputation: 37

You can simply use:

#ifdef DEBUG
    #define DEBUG_PRINT printf
#else
    #define DEBUG_PRINT
#endif

Upvotes: 2

Aidan Cully
Aidan Cully

Reputation: 5507

I've seen this idiom a fair amount:

#ifdef DEBUG
# define DEBUG_PRINT(x) printf x
#else
# define DEBUG_PRINT(x) do {} while (0)
#endif

Use it like:

DEBUG_PRINT(("var1: %d; var2: %d; str: %s\n", var1, var2, str));

The extra parentheses are necessary, because some older C compilers don't support var-args in macros.

Upvotes: 49

mipadi
mipadi

Reputation: 411380

Something like:

#ifdef DEBUG
#define DEBUG_PRINT(fmt, args...)    fprintf(stderr, fmt, ## args)
#else
#define DEBUG_PRINT(fmt, args...)    /* Don't do anything in release builds */
#endif

Upvotes: 22

Related Questions