您将调试信息报告给stderr 而不是stdout 的原因之一是,stdout 可能会沿着管道发送,而您的诊断将与实际数据一起使用,从而混淆管道的后续阶段。
如果您可能想要重定向输出,或添加时间戳(或 PID 或任何其他信息),请不要直接使用 fprintf()。调用您自己设计的函数,以您想要的方式处理您想要的信息。
因此,您的宏可能是:
extern void dbg_print(const char *fmt, ...);
#define DEBUG_PRINT(fmt, ...) \
do { if (DEBUG_TEST) dbg_print(fmt, __VA_ARGS__); } while (0)
或者:
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)
这包括信息中的函数名、文件名和行号
例如,我有一个中等复杂的包可以做到这一点。核心内部例程之一是:
/* err_stdio - report error via stdio */
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));
}
调试包装器可以使用适当的标志调用该函数,并生成所需的输出。系统的其他部分控制使用的文件流(stderr 是默认值,但有一个功能可以将输出重定向到任何其他流),等等。
如果您通过在调试宏中直接使用fprintf() 来限制自己,那么您会被fprintf() 的功能所困扰,或者重新编译所有内容。
另请参阅我对'C #define macro for debug printing' 的回答,了解有关调试宏以及如何使用它们的更多信息(尽管看起来你已经接受了我在船上所说的大部分内容)。