在 C 中打印不同调试消息的正确方法?
Proper way to print different debug messages in C?
在使用和不使用 DEBUG 标志进行编译时,我需要针对相同的错误打印 msg1 和 msg2。例如
fprintf( stderr,
#ifdef DEBUG
"error msg1 %s",__FILE__
#else
"error msg2"
#endif
);
或其他方式可能是将这些 msg1
和 msg2
传递给函数并使用 vfprintf()
打印它。
第二种方法可能会有 运行 时间开销。所以,我只是想知道这样做的更好方法是什么?
例如一个用例可能是需要使用 info
和 debug
标志编译代码。 info
可能是与用户相关的消息,debug
用于调试目的。
有什么建议么?
无条件调用 vfprintf
确实会带来一些额外的开销,用于打包额外参数 a
,以便与可变参数列表函数一起使用。而且,条件编译可以让编译器注意到在DEBUG
模式下调用fprintf
除了格式字符串之外没有传递参数,而将其替换为fputs("error msg1", stderr)
*
但是,这种开销很小,您不太可能注意到它,因为写入是无条件发生的,并且它将支配调用的时间。
* DEBUG
输出提供比非调试输出少 的细节的情况并不常见;通常,它是相反的。
您的调试标志是预处理器宏,因此将在编译时选择错误消息,这是您想要的行为吗?
我建议采用稍微不同的方法:
#define PRINT_INFO(msg1,msg2) if(dbg){fprintf(stderr,msg1);}\
else{fprintf(stderr,msg2);}
其中 dbg
标志可以在 运行 时间打开和关闭
您可以使用 variadic macros 进行更多尝试:
#define PRINT_INFO_VAR(msg1,msg2...) if(dbg){fprintf(stderr,msg1);}\
else{fprintf(stderr,msg2);}
对于您给出的示例,它看起来像这样:
PRINT_INFO_VAR(msg1,msg2,a)
通常在代码中使用跟踪来帮助调试它,因此例如在您的 NULL 指针测试中,您可以添加诸如 if (ptr==NULL) DEBUG("Entering Null pointer");
之类的东西。我只是告诉你,因为我不明白你为什么要同时使用 msg1
和 msg2
。
我通常使用宏 DEBUG
和全局变量 verbose
:
#define DEBUG(...)\
if(verbose && SHOW_ERROR) {\
printf("Error : %s, %d",__FUNCTION__, __LINE__);\
printf(__VA_ARGS__);\
}\
else if (verbose && SHOW_WARNING) {\
printf("Warning : %s, %d",__FUNCTION__, __LINE__);\
printf(__VA_ARGS__);\
}
示例:
#include <stdio.h>
#define SHOW_ERROR 1
#define SHOW_WARNING 2
int verbose = 1;
int main()
{
DEBUG("THIS WILL SHOW ERROR MSG");
verbose = 2;
DEBUG("THIS WILL SHOW WARNING MSG");
}
希望能帮到你。
在使用和不使用 DEBUG 标志进行编译时,我需要针对相同的错误打印 msg1 和 msg2。例如
fprintf( stderr,
#ifdef DEBUG
"error msg1 %s",__FILE__
#else
"error msg2"
#endif
);
或其他方式可能是将这些 msg1
和 msg2
传递给函数并使用 vfprintf()
打印它。
第二种方法可能会有 运行 时间开销。所以,我只是想知道这样做的更好方法是什么?
例如一个用例可能是需要使用 info
和 debug
标志编译代码。 info
可能是与用户相关的消息,debug
用于调试目的。
有什么建议么?
无条件调用 vfprintf
确实会带来一些额外的开销,用于打包额外参数 a
,以便与可变参数列表函数一起使用。而且,条件编译可以让编译器注意到在DEBUG
模式下调用fprintf
除了格式字符串之外没有传递参数,而将其替换为fputs("error msg1", stderr)
*
但是,这种开销很小,您不太可能注意到它,因为写入是无条件发生的,并且它将支配调用的时间。
* DEBUG
输出提供比非调试输出少 的细节的情况并不常见;通常,它是相反的。
您的调试标志是预处理器宏,因此将在编译时选择错误消息,这是您想要的行为吗?
我建议采用稍微不同的方法:
#define PRINT_INFO(msg1,msg2) if(dbg){fprintf(stderr,msg1);}\
else{fprintf(stderr,msg2);}
其中 dbg
标志可以在 运行 时间打开和关闭
您可以使用 variadic macros 进行更多尝试:
#define PRINT_INFO_VAR(msg1,msg2...) if(dbg){fprintf(stderr,msg1);}\
else{fprintf(stderr,msg2);}
对于您给出的示例,它看起来像这样:
PRINT_INFO_VAR(msg1,msg2,a)
通常在代码中使用跟踪来帮助调试它,因此例如在您的 NULL 指针测试中,您可以添加诸如 if (ptr==NULL) DEBUG("Entering Null pointer");
之类的东西。我只是告诉你,因为我不明白你为什么要同时使用 msg1
和 msg2
。
我通常使用宏 DEBUG
和全局变量 verbose
:
#define DEBUG(...)\
if(verbose && SHOW_ERROR) {\
printf("Error : %s, %d",__FUNCTION__, __LINE__);\
printf(__VA_ARGS__);\
}\
else if (verbose && SHOW_WARNING) {\
printf("Warning : %s, %d",__FUNCTION__, __LINE__);\
printf(__VA_ARGS__);\
}
示例:
#include <stdio.h>
#define SHOW_ERROR 1
#define SHOW_WARNING 2
int verbose = 1;
int main()
{
DEBUG("THIS WILL SHOW ERROR MSG");
verbose = 2;
DEBUG("THIS WILL SHOW WARNING MSG");
}
希望能帮到你。