1
前言
printf調(diào)試是嵌入式調(diào)試的基本手段,而且是非常重要的手段,我認(rèn)為相比單步調(diào)試更加有用有效,特別是單片機(jī)之后跑系統(tǒng),單步調(diào)試效率更加低下了,我們?cè)诠ぷ饔龅絙ug的時(shí)候,我們第一時(shí)間就想知道那些該死的日志有沒有保存下來,這樣好讓我們程序員裝逼一波把問題解決。
printf宏定義調(diào)試非常重要,有些日志在開發(fā)的時(shí)候才需要打開,發(fā)布的時(shí)候需要關(guān)閉,但是在代碼上又需要保留下次調(diào)試,所以我們?cè)谡{(diào)試的時(shí)候才打開調(diào)試宏定義,而且printf會(huì)占用空間,很多芯片的空間非常有限,更應(yīng)該關(guān)閉調(diào)試宏。
下面就直接進(jìn)入正題,說一下調(diào)試的技巧
2
正文
1、 編譯器內(nèi)置宏
先介紹幾個(gè)編譯器內(nèi)置的宏定義,這些宏定義不僅可以幫助我們完成跨平臺(tái)的源碼編寫,靈活使用也可以巧妙地幫我們輸出非常有用的調(diào)試信息。
ANSI C標(biāo)準(zhǔn)中有幾個(gè)標(biāo)準(zhǔn)預(yù)定義宏(也是常用的):
__LINE__:在源代碼中插入當(dāng)前源代碼行號(hào);
__FILE__:在源文件中插入當(dāng)前源文件名;
__DATE__:在源文件中插入當(dāng)前的編譯日期
__TIME__:在源文件中插入當(dāng)前編譯時(shí)間;
__STDC__:當(dāng)要求程序嚴(yán)格遵循ANSI C標(biāo)準(zhǔn)時(shí)該標(biāo)識(shí)被賦值為1;
__cplusplus:當(dāng)編寫C++程序時(shí)該標(biāo)識(shí)符被定義。
編譯器在進(jìn)行源碼編譯的時(shí)候,會(huì)自動(dòng)將這些宏替換為相應(yīng)內(nèi)容。
2、最基本的用法
打開宏的時(shí)候輸出
關(guān)閉宏的時(shí)候輸出
3、換個(gè)高級(jí)的用法
代碼如下
#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
在線編譯器網(wǎng)址:https://tool.lu/coderunner/
4、## __VA_ARGS__ ... 宏和可變參數(shù)
在GNU C中,宏可以接受可變數(shù)目的參數(shù),就象函數(shù)一樣
例如:
#definepr_debug(fmt,arg...) printk(KERN_DEBUGfmt,##arg)
用可變參數(shù)宏(variadic macros)傳遞可變參數(shù)表
你可能很熟悉在函數(shù)中使用可變參數(shù)表,如:
voidprintf(constchar*format,...);
直到最近,可變參數(shù)表還是只能應(yīng)用在真正的函數(shù)中,不能使用在宏中。
C99編譯器標(biāo)準(zhǔn)允許你可以定義可變參數(shù)宏(variadic macros),這樣你就可以
使用擁有可以變化的參數(shù)表的宏。可變參數(shù)宏就像下面這個(gè)樣子:
#definedebug(...)printf(__VA_ARGS__)
缺省號(hào)代表一個(gè)可以變化的參數(shù)表。使用保留名 __VA_ARGS__ 把參數(shù)傳遞給宏。
當(dāng)宏的調(diào)用展開時(shí),實(shí)際的參數(shù)就傳遞給 printf()了
例如:
debug("Y=%d ",y);
而處理器會(huì)把宏的調(diào)用替換成:
printf("Y=%d ",y);
因?yàn)閐ebug()是一個(gè)可變參數(shù)宏,你能在每一次調(diào)用中傳遞不同數(shù)目的參數(shù):
debug("test");//一個(gè)參數(shù)
用GCC和C99的可變參數(shù)宏, 更方便地打印調(diào)試信息
可變參數(shù)宏不被ANSI/ISO C++ 所正式支持。因此,你應(yīng)當(dāng)檢查你的編譯器,看它是否支持這項(xiàng)技術(shù)。
可變參數(shù)的宏里的'##'操作說明帶有可變參數(shù)的宏(Macros with a Variable Number of Arguments)
5、舉個(gè)栗子-Linux內(nèi)核調(diào)試宏
下面是Android touchscreen驅(qū)動(dòng)的調(diào)試宏用法,看這樣的寫法就是一個(gè)大神了,給大家借鑒。
//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
審核編輯:劉清
-
編譯器
+關(guān)注
關(guān)注
1文章
1623瀏覽量
49108 -
GNU
+關(guān)注
關(guān)注
0文章
143瀏覽量
17492 -
嵌入式調(diào)試器
+關(guān)注
關(guān)注
1文章
4瀏覽量
8956 -
Printf
+關(guān)注
關(guān)注
0文章
83瀏覽量
13650
原文標(biāo)題:?jiǎn)尾秸{(diào)試好用,printf宏也挺香~
文章出處:【微信號(hào):最后一個(gè)bug,微信公眾號(hào):最后一個(gè)bug】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論