之前一直是到處寫printf來列印調試信息,不需要是還得一個一個註釋掉.之後上網查詢發現有很多方法來進行DEBUG列印,參數可變而且方便一次性開關. #define DEBUG(fmt,...) printf (fmt,lxx_va_args) 這裡的“…”指的是可變參數. int main() {...
之前一直是到處寫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”); //有問題,需要更改巨集定義,在前加上##