0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

printf調(diào)試的技巧

lilihe92 ? 來(lái)源:嵌入式Linux ? 2023-05-10 09:31 ? 次閱讀

1

前言

printf調(diào)試是嵌入式調(diào)試的基本手段,而且是非常重要的手段,我認(rèn)為相比單步調(diào)試更加有用有效,特別是單片機(jī)之后跑系統(tǒng),單步調(diào)試效率更加低下了,我們?cè)诠ぷ饔龅絙ug的時(shí)候,我們第一時(shí)間就想知道那些該死的日志有沒(méi)有保存下來(lái),這樣好讓我們程序員裝逼一波把問(wèn)題解決。

printf宏定義調(diào)試非常重要,有些日志在開(kāi)發(fā)的時(shí)候才需要打開(kāi),發(fā)布的時(shí)候需要關(guān)閉,但是在代碼上又需要保留下次調(diào)試,所以我們?cè)谡{(diào)試的時(shí)候才打開(kāi)調(diào)試宏定義,而且printf會(huì)占用空間,很多芯片的空間非常有限,更應(yīng)該關(guān)閉調(diào)試宏。

下面就直接進(jìn)入正題,說(shuō)一下調(diào)試的技巧

2

正文

1、 編譯器內(nèi)置宏

先介紹幾個(gè)編譯器內(nèi)置的宏定義,這些宏定義不僅可以幫助我們完成跨平臺(tái)的源碼編寫(xiě),靈活使用也可以巧妙地幫我們輸出非常有用的調(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)編寫(xiě)C++程序時(shí)該標(biāo)識(shí)符被定義。

編譯器在進(jìn)行源碼編譯的時(shí)候,會(huì)自動(dòng)將這些宏替換為相應(yīng)內(nèi)容。

2、最基本的用法

打開(kāi)宏的時(shí)候輸出

09f9e1b8-ee7a-11ed-90ce-dac502259ad0.png

關(guān)閉宏的時(shí)候輸出

0a0cc72e-ee7a-11ed-90ce-dac502259ad0.png

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)用展開(kāi)時(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ù)的宏里的'##'操作說(shuō)明帶有可變參數(shù)的宏(Macros with a Variable Number of Arguments)

5、舉個(gè)栗子-Linux內(nèi)核調(diào)試宏

下面是Android touchscreen驅(qū)動(dòng)的調(diào)試宏用法,看這樣的寫(xiě)法就是一個(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>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





審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 編譯器
    +關(guān)注

    關(guān)注

    1

    文章

    1634

    瀏覽量

    49134
  • GNU
    GNU
    +關(guān)注

    關(guān)注

    0

    文章

    143

    瀏覽量

    17494
  • 嵌入式調(diào)試器
    +關(guān)注

    關(guān)注

    1

    文章

    4

    瀏覽量

    8956
  • Printf
    +關(guān)注

    關(guān)注

    0

    文章

    83

    瀏覽量

    13662

原文標(biāo)題:?jiǎn)尾秸{(diào)試好用,printf宏也挺香~

文章出處:【微信號(hào):最后一個(gè)bug,微信公眾號(hào):最后一個(gè)bug】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    keil5中想確認(rèn)工程中某一個(gè).c文件是否出錯(cuò),如何利用printf調(diào)試?

    現(xiàn)在想確認(rèn)工程中某一個(gè).c文件是否出錯(cuò),如何利用printf調(diào)試
    發(fā)表于 03-21 08:03

    【NUCLEO-F412ZG試用體驗(yàn)】2:調(diào)試準(zhǔn)備測(cè)量函數(shù)運(yùn)行時(shí)間

    到stlink的,如下圖所示:用STM32F412的串口3發(fā)送數(shù)據(jù),就可以和電腦進(jìn)行通信了。除了用串口調(diào)試,還可以用ITM功能,進(jìn)行DEBUG printf調(diào)試還可以用ITM功能測(cè)量程序運(yùn)行時(shí)
    發(fā)表于 12-02 22:22

    如何去解決STM32串口打印輸出亂碼的現(xiàn)象

    STM32串口打印輸出亂碼的解決辦法前言最近在試用uFUN開(kāi)發(fā)板,下載配套的Demo程序,串口數(shù)據(jù)輸出正常,當(dāng)使用另一個(gè)模板工程,調(diào)用串口printf調(diào)試功能時(shí),輸出的卻是亂碼,最后發(fā)現(xiàn)是外部晶振
    發(fā)表于 08-12 06:08

    使用STM32最小系統(tǒng)要注意哪些問(wèn)題呢

    STM32最小系統(tǒng)使用注意事項(xiàng)使用HAL庫(kù)CubeMX工具使用printf調(diào)試串口板子燒錄程序后沒(méi)反應(yīng)使用HAL庫(kù)CubeMX工具在System Core->SYS里選擇Debug方式,否則
    發(fā)表于 11-25 09:10

    如何為stm32-f429啟用類似SWD/SWO printf()的調(diào)試功能?

    我對(duì) stm32 和 arm 開(kāi)發(fā)完全陌生,最近得到了我的 stm32-f429(ZIT6) 發(fā)現(xiàn)工具包。我只是遵循了一些教程,但無(wú)法正確啟用 SWO printf() 之類的功能,我遵循了一些
    發(fā)表于 12-27 06:46

    如何在STM32CubeIDE上為Cortex M0+進(jìn)行“快速”調(diào)試?

    printf 調(diào)試?或者,有沒(méi)有一種快速的方法可以讓我了解我的代碼在跳入和跳出中斷時(shí)是如何執(zhí)行的?筆記:我知道這個(gè)文件:https : //www.st.com/resource/en
    發(fā)表于 02-03 08:31

    ESP-WROVER-KIT開(kāi)發(fā)板不能用于開(kāi)發(fā)涉及SD卡的代碼?

    如果要使用調(diào)試器,就沒(méi)有辦法為ESP32開(kāi)發(fā)嗎?您有什么建議 - 將此卡發(fā)回并進(jìn)行 PrintF() 調(diào)試?
    發(fā)表于 03-01 07:41

    如何通過(guò)USB PC終端使用printf()調(diào)試OM13093評(píng)估板?

    幫助:通過(guò) USB PC 終端使用 printf() 調(diào)試 OM13093 評(píng)估板我在 2018 年找到了一篇類似的帖子,但問(wèn)題沒(méi)有得到直接回答——如何設(shè)置 OM13093 評(píng)估板硬件
    發(fā)表于 03-23 09:01

    RT1170 EVK MCUXpresso“SWD配置”檢測(cè)到0個(gè)可用的SWD設(shè)備?

    一切都調(diào)試得很好,然后我開(kāi)始遇到這個(gè)問(wèn)題。它是在嘗試讓 M4 控制 PRINTF 調(diào)試并調(diào)用 BOARD_InitDebugConsole 而不是 M7 之后啟動(dòng)的我嘗試使用 LPCScrypt 和 program_CMSIS.
    發(fā)表于 04-11 06:27

    ESP-WROVER-KIT開(kāi)發(fā)板不能用于開(kāi)發(fā)涉及SD卡的代碼?

    如果要使用調(diào)試器,就沒(méi)有辦法為ESP32開(kāi)發(fā)嗎?您有什么建議 - 將此卡發(fā)回并進(jìn)行 PrintF() 調(diào)試?
    發(fā)表于 04-12 08:37

    STM8S串口打印調(diào)試信息(不使用printf)

    STM8S串口打印調(diào)試信息(不使用printf),感興趣可以看看。
    發(fā)表于 07-25 18:52 ?51次下載

    51單片機(jī)-printf調(diào)試用法

    #include <stdio.h>#include <reg52.h> void InitUART(void)//使用定時(shí)器1作為串口波特率發(fā)生器{ TH1 = 0xF3; //晶振12mhz 波特率串口上設(shè)為2400才不顯示亂碼代碼是4800 TL1 = TH1; TMOD |= 0x20; //定時(shí)器1方式2 SCON ...
    發(fā)表于 11-11 20:06 ?2次下載
    51單片機(jī)-<b class='flag-5'>printf</b><b class='flag-5'>調(diào)試</b>用法

    STM32最小系統(tǒng)使用注意事項(xiàng)

    STM32最小系統(tǒng)使用注意事項(xiàng)使用HAL庫(kù)CubeMX工具使用printf調(diào)試串口板子燒錄程序后沒(méi)反應(yīng)使用HAL庫(kù)CubeMX工具在System Core->SYS里選擇Debug方式
    發(fā)表于 11-17 17:36 ?6次下載
    STM32最小系統(tǒng)使用注意事項(xiàng)

    51單片機(jī)串口通信調(diào)試printf函數(shù)重定向輸出打印

    51單片機(jī)串口通信以及printf調(diào)試串行通信1.串口初始化串口工作方式波特率設(shè)置通過(guò)軟件直接生成串口初始化代碼2.輸出到串口3.發(fā)送字符串到串口4.printf重定向到串口5.補(bǔ)充print
    發(fā)表于 11-20 16:36 ?16次下載
    51單片機(jī)串口通信<b class='flag-5'>調(diào)試</b><b class='flag-5'>printf</b>函數(shù)重定向輸出打印

    STM32串口打印輸出亂碼的解決辦法

    最近在試用uFUN開(kāi)發(fā)板,下載配套的Demo程序,串口數(shù)據(jù)輸出正常,當(dāng)使用另一個(gè)模板工程,調(diào)用串口printf調(diào)試功能時(shí),輸出的卻是亂碼,最...
    發(fā)表于 01-26 18:29 ?2次下載
    STM32串口打印輸出亂碼的解決辦法