可变参数宏(DEBUG)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了可变参数宏(DEBUG)相关的知识,希望对你有一定的参考价值。
之前一直是到处写printf来打印调试信息,不需要是还得一个一个注释掉.之后上网查询发现有很多方法来进行DEBUG打印,参数可变而且方便一次性开关.
#define DEBUG(fmt,...) printf (fmt,__VA_ARGS__) 这里的“…”指的是可变参数.
int main() { DEBUG(“hello %d”,10); return 0; }
有时候,有个模块有输出信息,错误信息等.如果想单独打开某一部分,可以如此设计:
1: #define DRV_DEBUG 12: #define DRV_DEBUG_IN 0x00013: #define DRV_DEBUG_OUT 0x00024: #define DRV_DEBUG_ERR 0x00045: #define DRV_DEBUG_ALL 0xFFFF6: #if DRV_DEBUG
7: unsigned int drv_flags = DRV_DEBUG_ERR | DRV_DEBUG_OUT;8: #define DRV_PRINT(flag, fmt, …)9: do{
10: if (drv_flags & flag){
11: printf(fmt, __VA_ARGS__);}
12: }while(0)
13: #else
14: #define DRV_PRINT(fmt,…)15: #endif
这样,我只要打印OUT和ERR:
1: void drv_write(char * msg_out)2: {3: DRV_PRINT(DRV_DEBUG_OUT,"%s", msg_out); //输出4: DRV_PRINT(DRV_DEBUG_ERR,"%s", msg_out); //输出5: DRV_PRINT(DRV_DEBUG_IN,"%s", msg_out); //不输出6: }进一步,可以设计针对整个系统不同模块的LOG输出控制!TCP/IP协议栈实现Lwip就是这么干的.
但是发现光有printf还不够,虽然调试信息是出来了,但是在这么多的调试信息中并不能一下子知道这信息是从哪里打印出来的.所以查到用另一种方法可以将文件名和源码位置都打印出来.
在ANSI C中有这样几个宏
__LINE__:插入当前行号
__FILE__:插入当前原文件名
__DATE__:插入当前编译日期
__TIME__:插入当前编译时间
所以宏就变成这样子了DEBUG(fmt,…) printf(“FILE:”__FILE__”“,LINE:%d:”fmt”\n”,__LINE__,##__VA_ARGS__)
这里特别注意下##__VA_ARGS__这里的##是很有必要的,因为他的意思是如果没有参数则让预处理器忽略前面一个逗号.上面第一段的写法不加参数是出错的.所以第一段写法必须带参数.
DRV_PRINT(DRV_DEBUG_OUT,“hello world”); //有问题,需要更改宏定义,在前加上##
以上是关于可变参数宏(DEBUG)的主要内容,如果未能解决你的问题,请参考以下文章