1
前言
printf調試是嵌入式調試的基本手段,而且是非常重要的手段,我認為相比單步調試更加有用有效,特別是單片機之后跑系統,單步調試效率更加低下了,我們在工作遇到bug的時候,我們第一時間就想知道那些該死的日志有沒有保存下來,這樣好讓我們程序員裝逼一波把問題解決。
printf宏定義調試非常重要,有些日志在開發的時候才需要打開,發布的時候需要關閉,但是在代碼上又需要保留下次調試,所以我們在調試的時候才打開調試宏定義,而且printf會占用空間,很多芯片的空間非常有限,更應該關閉調試宏。
下面就直接進入正題,說一下調試的技巧
2
正文
1、 編譯器內置宏
先介紹幾個編譯器內置的宏定義,這些宏定義不僅可以幫助我們完成跨平臺的源碼編寫,靈活使用也可以巧妙地幫我們輸出非常有用的調試信息。
ANSI C標準中有幾個標準預定義宏(也是常用的):
__LINE__:在源代碼中插入當前源代碼行號;
__FILE__:在源文件中插入當前源文件名;
__DATE__:在源文件中插入當前的編譯日期
__TIME__:在源文件中插入當前編譯時間;
__STDC__:當要求程序嚴格遵循ANSI C標準時該標識被賦值為1;
__cplusplus:當編寫C++程序時該標識符被定義。
編譯器在進行源碼編譯的時候,會自動將這些宏替換為相應內容。
2、最基本的用法
打開宏的時候輸出
關閉宏的時候輸出
3、換個高級的用法
代碼如下
#include#define__DEBUG__ #ifdef__DEBUG__ #defineDEBUG(format,...)printf("Date:"__DATE__",File:"__FILE__",Line:%05d:"format" ",__LINE__,##__VA_ARGS__) #else #defineDEBUG(format,...) #endif intmain(intargc,char**argv){ charstr[]="HelloWorld"; DEBUG("%s",str); return0; }
輸出如下
Date:Oct52018,File:/code/main.c,Line:00013:HelloWorld sandbox>exitedwithstatus0
在線編譯器網址:https://tool.lu/coderunner/
4、## __VA_ARGS__ ... 宏和可變參數
在GNU C中,宏可以接受可變數目的參數,就象函數一樣
例如:
#definepr_debug(fmt,arg...) printk(KERN_DEBUGfmt,##arg)
用可變參數宏(variadic macros)傳遞可變參數表
你可能很熟悉在函數中使用可變參數表,如:
voidprintf(constchar*format,...);
直到最近,可變參數表還是只能應用在真正的函數中,不能使用在宏中。
C99編譯器標準允許你可以定義可變參數宏(variadic macros),這樣你就可以
使用擁有可以變化的參數表的宏??勺儏岛昃拖裣旅孢@個樣子:
#definedebug(...)printf(__VA_ARGS__)
缺省號代表一個可以變化的參數表。使用保留名 __VA_ARGS__ 把參數傳遞給宏。
當宏的調用展開時,實際的參數就傳遞給 printf()了
例如:
debug("Y=%d ",y);
而處理器會把宏的調用替換成:
printf("Y=%d ",y);
因為debug()是一個可變參數宏,你能在每一次調用中傳遞不同數目的參數:
debug("test");//一個參數
用GCC和C99的可變參數宏, 更方便地打印調試信息
可變參數宏不被ANSI/ISO C++ 所正式支持。因此,你應當檢查你的編譯器,看它是否支持這項技術。
可變參數的宏里的'##'操作說明帶有可變參數的宏(Macros with a Variable Number of Arguments)
5、舉個栗子-Linux內核調試宏
下面是Android touchscreen驅動的調試宏用法,看這樣的寫法就是一個大神了,給大家借鑒。
//Logdefine #defineGTP_ERROR(fmt,arg...)printk("<<-GTP-ERROR->>"fmt" ",##arg) #ifDEBUG_SWITCH #defineGTP_INFO(fmt,arg...)printk("<<-GTP-INFO->>"fmt" ",##arg) #defineGTP_DEBUG(fmt,arg...)do{ if(GTP_DEBUG_ON) printk("<<-GTP-DEBUG->>[%d]"fmt" ",__LINE__,##arg); }while(0) #defineGTP_DEBUG_ARRAY(array,num)do{ s32i; u8*a=array; if(GTP_DEBUG_ARRAY_ON) { printk("<<-GTP-DEBUG-ARRAY->> "); for(i=0;i(num);?i++) ????????????????????????????????????????????{ ????????????????????????????????????????????????printk("%02x???",?(a)[i]); ????????????????????????????????????????????????if?((i?+?1?)?%10?==?0) ????????????????????????????????????????????????{ ????????????????????????????????????????????????????printk(" "); ????????????????????????????????????????????????} ????????????????????????????????????????????} ????????????????????????????????????????????printk(" "); ????????????????????????????????????????} ???????????????????????????????????????}while(0) #define?GTP_DEBUG_FUNC()???????????????do{ ?????????????????????????????????????????if(GTP_DEBUG_FUNC_ON) ?????????????????????????????????????????printk("?????<<-GTP-FUNC->>Func:%s@Line:%d ",__func__,__LINE__); }while(0) #else #defineGTP_INFO(fmt,arg...) #defineGTP_DEBUG(fmt,arg...) #defineGTP_DEBUG_ARRAY(array,num) #defineGTP_DEBUG_FUNC() #endif
審核編輯:劉清
-
編譯器
+關注
關注
1文章
1618瀏覽量
49051 -
GNU
+關注
關注
0文章
143瀏覽量
17479 -
嵌入式調試器
+關注
關注
1文章
4瀏覽量
8954 -
Printf
+關注
關注
0文章
81瀏覽量
13625
原文標題:單步調試好用,printf宏也挺香~
文章出處:【微信號:最后一個bug,微信公眾號:最后一個bug】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論