Trying to create a macro which can be used for print debug messages when DEBUG is defined, like the following pseudo code:
#define DEBUG 1
#define debug_prin
For a portable (ISO C90) implementation, you could use double parentheses, like this;
#include <stdio.h>
#include <stdarg.h>
#ifndef NDEBUG
# define debug_print(msg) stderr_printf msg
#else
# define debug_print(msg) (void)0
#endif
void
stderr_printf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
int
main(int argc, char *argv[])
{
debug_print(("argv[0] is %s, argc is %d\n", argv[0], argc));
return 0;
}
or (hackish, wouldn't recommend it)
#include <stdio.h>
#define _ ,
#ifndef NDEBUG
# define debug_print(msg) fprintf(stderr, msg)
#else
# define debug_print(msg) (void)0
#endif
int
main(int argc, char *argv[])
{
debug_print("argv[0] is %s, argc is %d"_ argv[0] _ argc);
return 0;
}
This is what I use:
#if DBG
#include <stdio.h>
#define DBGPRINT printf
#else
#define DBGPRINT(...) /**/
#endif
It has the nice benefit to handle printf properly, even without additional arguments. In case DBG ==0, even the dumbest compiler gets nothing to chew upon, so no code is generated.
According to http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html,
there should be a ##
before __VA_ARGS__
.
Otherwise, a macro #define dbg_print(format, ...) printf(format, __VA_ARGS__)
will not compile the following example: dbg_print("hello world");
.
My favourite of the below is var_dump
, which when called as:
var_dump("%d", count);
produces output like:
patch.c:150:main(): count = 0
Credit to @"Jonathan Leffler". All are C89-happy:
Code
#define DEBUG 1
#include <stdarg.h>
#include <stdio.h>
void debug_vprintf(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
}
/* Call as: (DOUBLE PARENTHESES ARE MANDATORY) */
/* var_debug(("outfd = %d, somefailed = %d\n", outfd, somefailed)); */
#define var_debug(x) do { if (DEBUG) { debug_vprintf ("%s:%d:%s(): ", \
__FILE__, __LINE__, __func__); debug_vprintf x; }} while (0)
/* var_dump("%s" variable_name); */
#define var_dump(fmt, var) do { if (DEBUG) { debug_vprintf ("%s:%d:%s(): ", \
__FILE__, __LINE__, __func__); debug_vprintf ("%s = " fmt, #var, var); }} while (0)
#define DEBUG_HERE do { if (DEBUG) { debug_vprintf ("%s:%d:%s(): HERE\n", \
__FILE__, __LINE__, __func__); }} while (0)
I believe this variation of the theme gives debug categories without the need to have a separate macro name per category.
I used this variation in an Arduino project where program space is limited to 32K and dynamic memory is limited to 2K. The addition of debug statements and trace debug strings quickly uses up space. So it is essential to be able to limit the debug trace that is included at compile time to the minimum necessary each time the code is built.
#ifndef DEBUG_H
#define DEBUG_H
#define PRINT(DEBUG_CATEGORY, VALUE) do { if (DEBUG_CATEGORY & DEBUG_MASK) Serial.print(VALUE);} while (0);
#endif
#define DEBUG_MASK 0x06
#include "Debug.h"
...
PRINT(4, "Time out error,\t");
...
I use something like this:
#ifdef DEBUG
#define D if(1)
#else
#define D if(0)
#endif
Than I just use D as a prefix:
D printf("x=%0.3f\n",x);
Compiler sees the debug code, there is no comma problem and it works everywhere. Also it works when printf
is not enough, say when you must dump an array or calculate some diagnosing value that is redundant to the program itself.
EDIT: Ok, it might generate a problem when there is else
somewhere near that can be intercepted by this injected if
. This is a version that goes over it:
#ifdef DEBUG
#define D
#else
#define D for(;0;)
#endif