在程序中为了调试的方便经常会添加printf调试打印,但在产品正式发布时会将调试语句全部关掉,
这就涉及到如何关闭调试语句,可使用宏定义来达到调试的目的,如:
#define DEBUG printf
以后程序中就可以用
DEBUG("hello world\r\n");
要关闭调试语句时可以定义宏为:
#define DEBUG(fmt , ...)
即定义一个空宏即可,这样调试语句就会被编译器自动优化掉;
但这样做会有一个问题,如:
if(i > 0)
DEBUG("i > 0 \r\n");
i = 0;
上述程序片段的本意是在i大于0时打印,然后再使i等于0,即if语句只作用到DEBGU,
而不包含i = 0;这句话,但如果将调试关掉后程序就变成了
if(i > 0)
i = 0;
即if语句作用到了i = 0;这句话中去了,显然这违背了程序的本意;
因此我们就可以将if语句加上括号{ },不就可以啦,但你并不能要求所有代码人员都这么做,
况且if语句本身只包含一条语句时,是可以不用加括号的,因此别人不加括号也无可厚非,
那么程序就只能从宏定义本身入手了,这时我们可以用do{ ...}while(0)语句来实现:即
#define DEBUG do{ }while(0)
这样程序就被展来为:
if(i > 0)
do{ }while(0);
i = 0;
其中do{ }while(0);并未做任何实质的事情,但那完全可以限制住if语句的作用域,这样程序
就不会产生错误,同时do{ }while(0);语句也会被优化掉。
同理我们也可将调试宏定义修改为:
#define DEBUG(fmt, ...) do{ printf(fmt , ##__VA_ARGS__); }while(0)
这样调试宏定义就显得比较完美了,其中DEBUG(fmt, ...)中的fmt 为调试格式字符串,后面
的省略号表示其参数是可变的,而printf(fmt , ##__VA_ARGS__); 中的fmt 字符串可以完
全替代过来,而后面的__VA_ARGS__表示参数的具体内容,这在编译时会被编译器确定下来,而前面
的##连词符表示如果调试语句不带参数,就将将面的逗号去掉,以防语法出错,这样宏定义
就算彻底完美了。
#define DEBUG_EN1 // 0: close debug , 1: open debug
#if DEBUG_EN
#define DEBUG(fmt, ...) do{ printf(fmt , ##__VA_ARGS__); }while(0)
#else
#define DEBUG do{ }while(0)
#endif