Reputation: 149
I have found no way to merge the first printf into the second:
unsigned get_time_now(void) {return 1;}
#define DEBUG_PRINT 1
#define debug_tcprintf(fmt, ...) do { \
if (DEBUG_PRINT) { \
unsigned p_time_now = get_time_now(); \
printf ("%u ms ", p_time_now); \
printf(fmt, __VA_ARGS__); \
} \
} while (0)
I need to get this done to get an atomic debug_tcprintf. The macro above has been taken from this Stack Overflow question.
I am doing code in XC that runs on an XMOS multi-logical-core processor. It compiles XC, C and C++, but the code example is from a C code part. It is similar for XC except that it has a timer defined in the language.
If it's not possible to merge the two in one printf, an option may perhaps be to create a string and use sprintf instead? I'd rather not, since such an array might easily overflow.
Upvotes: 8
Views: 4900
Reputation: 9047
You need to use string concatenation and token pasting. Notice in the snippet below there is no comma after the first string literal -- this is intentional.
#define debug_tcprintf(fmt, ...) do { \
if (DEBUG_PRINT_HTTPD) { \
unsigned p_time_now = get_time_now (); \
printf ("%u ms " fmt, p_time_now, ##__VA_ARGS__); \
} \
} while (0)
The string concatenation allows you to prepend the "%u ms "
portion onto the supplied format string. Token pasting (the ##
operator) accounts for the possibility of your macro being invoked with or without additional variadic arguments (beyond just the format string).
This only works if you call the macro with a string literal as the format string.
Addendum: The way token-pasting is used in this example is actually a gcc extension to the standard C pre-processor. If you are not using the gcc compiler, you may need to omit the ##
operator. The downside to this is that you then cannot call your macro with only one argument; for example, debug_tcprintf ("hello world")
will not work. A simple workaround is to use debug_tcprintf ("%s", "hello world")
in such a scenario.
Upvotes: 5