日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

设计printf调试宏

發布時間:2025/6/15 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 设计printf调试宏 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

設計printf調試宏:在調試時打印調試信息,而產品代碼不顯示調試信息。

#define _DEBUG_ 0 #if _DEBUG_ #define ACCLOG(...) printf(__VA_ARGS__) #else #define ACCLOG(...) #endif

在代碼中可以如下使用以上的定義:

ACCLOG("test car...\n");

ACCLOG("find card:%s\n", car_str);??

重定向printf打印

嵌入式設備基本會配置RS232串口作為調試IO接口,假設底層串口單字節輸出函數為SERIAL_PutChar(),利用fputc()和fputs()重定向printf函數

void fputc(int byte, FILE* stream) {(void)stream;SERIAL_PutChar(byte); }void fputs(const char *pstr, FILE *stream) {(void)stream;while(*pstr){SERIAL_PutChar(*pstr++);} }

這樣在代碼里面利用printf()函數輸出的字符串都老老實實從調試串口出來

調試宏使用場景

某個C驅動模塊,希望在調試時打印調試信息,而產品代碼中不顯示調試信息。

v1--單參數宏

#define DRV_DEBUG 1 #if DRV_DEBUG#define DRV_PRINT(x) printf(x) #else#define DRV_PRINT(x) #endif

這個版本的DRV_PRINT(x)只能輸出單變量——純字符串

void foo() {DRV_PRINT("Driver Initialize Success!"); }

不需要打印調試信息時,更改DRV_DEBUG宏定義

#define DRV_DEBUG 0

當然也可以直接這樣定義

#define DRV_PRINT printf

但是如果宏調用了多個參數:

void foo() {DRV_PRINT("Driver Initialize Success: ver %d.%d !", 1, 2); }

產品代碼中的#define DRV_PRINT(x)將編譯錯誤!

怎么辦?一種處女座肯定接受不了的做法,多加對括號

void foo() {DRV_PRINT(("Driver Initialize Success: ver %d.%d !", 1, 2)); }

不管是調試代碼還是產品代碼,編譯都OK

v2--指定參數宏

#define DRV_DEBUG 1 #if DRV_DEBUG#define DRV_PRINT(fmt, val1, val2) printf(fmt, val1, val2) #else#define DRV_PRINT(fmt, val1, val2) #endif

如果只需要打印一個變量,第2個參數用隨意值填位,如

void foo() {DRV_PRINT("Driver Initialize Success: ver %d !", val1, 2); }

類似,如果有4個參數,就:

void foo() {DRV_PRINT("Driver Initialize Success: ver %d !", val1, 2, 3, 4); }

很傻,但是沒辦法:(,VxWorks 5.5內核代碼里就是這樣干的!

v3--參數數量可變宏

C90和C++中可將宏聲明為接受可變數量的自變量,如ARM編譯器是這樣的:

#define DRV_DEBUG 1 #if DRV_DEBUG#define DRV_PRINT(fmt, ...) printf(fmt, __VA_ARGS__) #else#define DRV_PRINT(fmt, ...) #endif

現在DRV_PRINT用法和printf完全一樣了,這么爽的功能,C2000編譯器卻不支持!

題外話,注意這個特性C90支持,而C90是C++的一個子集,但是C99和C++卻不兼容了

分層次LOG輸出

有時候,某個模塊,有輸入跟蹤信息,輸出信息,錯誤信息等,如果我想單獨打開某部分信息,可以這樣設計

#define DRV_DEBUG 1 #define DRV_DEBUG_IN 0x0001 #define DRV_DEBUG_OUT 0x0002 #define DRV_DEBUG_ERR 0x0004 #define DRV_DEBUG_ALL 0xFFFF #if DRV_DEBUGunsigned int drv_flags = DRV_DEBUG_ERR | DRV_DEBUG_OUT;#define DRV_PRINT(flag, fmt, ...) \do{\if(drv_flags & flag){\printf(fmt, __VA_ARGS__)}\}while(0) #else#define DRV_PRINT(fmt, ...) #endif

NOTE: 多行宏,注意換行前加\號

這樣,我只打印OUT和ERR:

void drv_write(char* msg_out) {DRV_PRINT(DRV_DEBUG_OUT, "Drivr write %s", msg_out); // 輸出DRV_PRINT(DRV_DEBUG_ERR, "Drivr write %s", msg_out); // 輸出DRV_PRINT(DRV_DEBUG_IN, "Drivr write %s", msg_out); // 不輸出 }

進一步,可以設計針對整個系統不同模塊的LOG輸出控制!TCP/IP協議棧實現Lwip就是這么干的!

總結

在嵌入式C語言里面,運用printf調試宏,有助于事后分析,定位BUG,多多益善!

總結

以上是生活随笔為你收集整理的设计printf调试宏的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。