One of the reasons you are reporting debugging information to stderr rather than stdout is because stdout can be piped and your diagnostics will go with the actual data, confusing the subsequent pipelines.
If you want to redirect the output or add timestamps (or PID or any other information), do not use fprintf() directly. Call the function of your own developer, which deals with the information that you want, as you want.
So your macro could be:
extern void dbg_print(const char *fmt, ...); #define DEBUG_PRINT(fmt, ...) \ do { if (DEBUG_TEST) dbg_print(fmt, __VA_ARGS__); } while (0)
Or:
extern void dbg_print(const char *func, const char *file, int line, const char *fmt, ...); #define DEBUG_PRINT(fmt, ...) \ do { if (DEBUG_TEST) dbg_print(__func__, __FILE__, __LINE__, fmt, __VA_ARGS__); } while (0)
This includes the function name, file name, and line number in the information.
For example, I have a moderately complex package that does this. One of the main internal procedures:
static void err_stdio(FILE *fp, int flags, int errnum, const char *format, va_list args) { if ((flags & ERR_NOARG0) == 0) fprintf(fp, "%s: ", arg0); if (flags & ERR_STAMP) { char timbuf[32]; fprintf(fp, "%s - ", err_time(timbuf, sizeof(timbuf))); } if (flags & ERR_PID) fprintf(fp, "pid=%d: ", (int)getpid()); vfprintf(fp, format, args); if (flags & ERR_ERRNO) fprintf(fp, "error (%d) %s\n", errnum, strerror(errnum)); }
Debug wrappers can call this function with the appropriate flags and generate the desired result. Other parts of the system control the file stream used ( stderr by default, but there is a function to redirect output to any other stream), etc.
If you restrict yourself using fprintf() directly in the debug macro, you are stuck with what fprintf() can do or recompile everything.
See also my answer to 'C # define macro for debug printing' for more information on debugging macros and how to use them (although it looks like this, I took a lot of what I say there on board already).