I want to make a simple macro that calls printf() twice like this
#ifdef ENABLE_DEBUGPRINTF
#define DEBUGPRINTF(msg) printf("At sim_time = %f:", sim_time); printf(msg);
#else
#define DEBUGPRINTF(msg) //evalutes to nothing
#endif
Now when I call
DEBUGPRINTF("Processed event type: %d with value %f\n", id, data)
It prints the first part "At sime_time = ... " correctly but the latter part where it says "Processed events ... " prints the value for id and data incorrectly.
Meanwhile
printf("Processed event type: %d with value %f\n", id, data);
Prints the values correctly.
When I try executing it by writing exactly out what I thought the macro would evaluate to, I have.
printf("At sim_time = %f:", sim_time); printf("Processed event type: %d with value %f\n", id, data);
This prints everything correctly! So why isn't my macro evaluating to this?
Because you want and are using the full flexibility of a regular printf
, what you want is a macro with a variadic
argument:
#ifdef ENABLE_DEBUGPRINTF
#define DEBUGPRINTF(msg...) \
printf("At sim_time = %f:", sim_time); printf(msg);
#else
#define DEBUGPRINTF(msg...) /*evalutes to nothing*/
#endif
I've done this many times before and I recommend encapsulating with do { } while (0)
:
#ifdef ENABLE_DEBUGPRINTF
#define DEBUGPRINTF(msg...) \
do { \
printf("At sim_time = %f:", sim_time); \
printf(msg); \
} while (0)
#else
#define DEBUGPRINTF(msg...) //evalutes to nothing
#endif
This allows you to do something like:
if (showit)
DEBUGPRINTF("hit the showit point -- showit=%d\n",showit);
Thus, the code that uses the macro doesn't have to know that it's actually two statements [or none]
UPDATE:
DEBUGPRINTF(msg...)
is not standard compliant, but some legacy compiler extension. You missed a comma before the ellipsis.
Perhaps, but, personally, I still prefer it, and have been using it in production code for 10+ years.
However, here are some resources for those that might wish to use the alternative ways:
- https://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html
- https://en.wikipedia.org/wiki/Variadic_macro
You declare DEBUGPRINTF
as taking one argument, but then you pass it three, so of course it's not working as you'd expect.
msg
is just "Processed event type: %d with value %f\n"
in your first example, and your second printf()
call is just pulling garbage for the %d
and the %f
, because your macro never tells it anything about id
or data
and so they never get passed to printf()
.
You want something like:
#define DEBUGPRINTF(msg, id, data) printf("At sim_time = %f:", sim_time); printf(msg, id, data);
or, if you need something more flexible, to play around with variadic macros.
Use a double ( nested) definition:
#define FIRST printf("…")
#define DEBUGMSG(msg) FIRST;printf(msg)
This has one argument in definition, and one argument in implementation.