2023年7月10日发(作者:)
__VA_ARGS__⽤法⾃定义调试信息的输出 调试信息的输出⽅法有很多种, 例如直接⽤printf, 或者出错时使⽤perror, fprintf等将信息直接打印到终端上, 在Qt上⾯⼀般使⽤qDebug,⽽守护进程则⼀般是使⽤syslog将调试信息输出到⽇志⽂件中等等... 使⽤标准的⽅法打印调试信息有时候不是很⽅便, 例如Qt编程, 在调试已有的代码时, 我想在打印调试信息的地⽅, 把代码位置也打印出来以⽅便定位错误, 或者需要在调试信息前⾯加⼀个前辍, 好⽅便在调试信息太多的时候可以⽤grep过滤⼀下, 仅显⽰本模块的调试信息, 这时就需要⼀个⼀个地修改已有的qDebug, 使其成为以下形式:
qDebug( "[模块名称] 调试信息 File:%s, Line:%d", __FILE__, __LINE__ );
这样的修改⽐较烦⼈, ⽽且⼀不⼩⼼会遗漏某个没改的... 为了能⽅便地管理调试信息的输出,⼀个⽐较简单的⽅法就是⾃已定义⼀个打印调试信息的宏, 然后替换原来的,废话就不多说了,直接给出⼀个现成的,下⾯是⼀个例⼦, 我⽤WiFi表⽰当前代码的模块名称,我要求在模块中的所有调试信息前⾯均带有[WiFi]前辍,这样我就能⽅便地只需使⽤命令⾏ | grep "WiFi"来过滤掉来⾃其它模块的调试信息了:#define qWiFiDebug(format, ...) qDebug("[WiFi] "format" File:%s, Line:%d, Function:%s", ##__VA_ARGS__, __FILE__, __LINE__ ,__FUNCTION__); 上⾯的宏是使⽤qDebug输出调试信息,在⾮Qt的程序中也可以改为printf,守护进程则可以改为syslog等等... 其中,决窍其实就是这⼏个宏 ##__VA_ARGS__, __FILE__, __LINE__ 和__FUNCTION__,下⾯介绍⼀下这⼏个宏: 1) __VA_ARGS__ 是⼀个可变参数的宏,很少⼈知道这个宏,这个可变参数的宏是新的C99规范中新增的,⽬前似乎只有gcc⽀持(VC6.0的编译器不⽀持)。 宏前⾯加上##的作⽤在于,当可变参数的个数为0时,这⾥的##起到把前⾯多余的","去掉的作⽤,否则会编译出错, 你可以试试。
2) __FILE__ 宏在预编译时会替换成当前的源⽂件名
3) __LINE__宏在预编译时会替换成当前的⾏号
4) __FUNCTION__宏在预编译时会替换成当前的函数名称 有了以上这⼏个宏,特别是有了__VA_ARGS__ ,调试信息的输出就变得灵活多了。
有时,我们想把调试信息输出到屏幕上,⽽有时则⼜想把它输出到⼀个⽂件中,可参考下⾯的例⼦://debug.c#include
#include//开启下⾯的宏表⽰程序运⾏在调试版本, 否则为发⾏版本, 这⾥假设只有调试版本才输出调试信息
#define _DEBUG#ifdef _DEBUG
//开启下⾯的宏就把调试信息输出到⽂件,注释即输出到终端
#define DEBUG_TO_FILE
#ifdef DEBUG_TO_FILE
//调试信息输出到以下⽂件
#define DEBUG_FILE "/tmp/debugmsg"
//调试信息的缓冲长度
#define DEBUG_BUFFER_MAX 4096
//将调试信息输出到⽂件中
#define printDebugMsg(moduleName, format, ...) {
char buffer[DEBUG_BUFFER_MAX+1]={0};
snprintf( buffer, DEBUG_BUFFER_MAX
, "[%s] "format" File:%s, Line:%dn", moduleName, ##__VA_ARGS__, __FILE__, __LINE__ );
FILE* fd = fopen(DEBUG_FILE, "a");
if ( fd != NULL ) {
fwrite( buffer, strlen(buffer), 1, fd );
fflush( fd );
fclose( fd );
}
}
#else
//将调试信息输出到终端
#define printDebugMsg(moduleName, format, ...)
printf( "[%s] "format" File:%s, Line:%dn", moduleName, ##__VA_ARGS__, __FILE__, __LINE__ );
#endif //end for #ifdef DEBUG_TO_FILE #else
//发⾏版本,什么也不做
#define printDebugMsg(moduleName, format, ...)
#endif //end for #ifdef _DEBUGint main(int argc, char** argv)
{
int data = 999;
printDebugMsg( "TestProgram", "data = %d", data );
return 0;
}
上⾯也说了,只有⽀持C99规范的gcc编译器才有__VA_ARGS__这个宏,如果不是gcc编译器,或者所⽤的gcc编译器版本不⽀持__VA_ARGS__宏怎么办? 可参考下⾯的代码⽚段,我们换⼀种做法,可先将可变参数转换成字符串后,再进⾏输出即可:void printDebugMsg( const char* format, ...)
{
char buffer[DEBUG_BUFFER_MAX_LENGTH + 1]={0}; va_list arg;
va_start (arg, format);
vsnprintf(buffer, DEBUG_BUFFER_MAX_LENGTH, format, arg);
va_end (arg); printf( "%s", buffer );
}
发布者:admin,转转请注明出处:http://www.yc00.com/web/1688986473a191845.html
评论列表(0条)