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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

printf 宏 调试技巧

發布時間:2023/12/20 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 printf 宏 调试技巧 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1 前言

printf調試是嵌入式調試的基本手段,而且是非常重要的手段,我認為相比單步調試更加有用有效,特別是單片機之后跑系統,單步調試效率更加低下了,我們在工作遇到bug的時候,我們第一時間就想知道那些該死的日志有沒有保存下來,這樣好讓我們程序員裝逼一波把問題解決。

printf宏定義調試非常重要,有些日志在開發的時候才需要打開,發布的時候需要關閉,但是在代碼上又需要保留下次調試,所以我們在調試的時候才打開調試宏定義,而且printf會占用空間,很多芯片的空間非常有限,更應該關閉調試宏。

下面就直接進入正題,說一下調試的技巧

?

2. 正文

?

1 編譯器內置宏

先介紹幾個編譯器內置的宏定義,這些宏定義不僅可以幫助我們完成跨平臺的源碼編寫,靈活使用也可以巧妙地幫我們輸出非常有用的調試信息。

ANSI C標準中有幾個標準預定義宏(也是常用的):

__LINE__:在源代碼中插入當前源代碼行號;

__FILE__:在源文件中插入當前源文件名;

__DATE__:在源文件中插入當前的編譯日期

__TIME__:在源文件中插入當前編譯時間;

__STDC__:當要求程序嚴格遵循ANSI C標準時該標識被賦值為1;

__cplusplus:當編寫C++程序時該標識符被定義。

編譯器在進行源碼編譯的時候,會自動將這些宏替換為相應內容。

?

2 最基本的用法

打開宏的時候輸出

?

?

關閉宏的時候輸出

?

?

3 換個高級的用法
????? ? 代碼如下

#include?<stdio.h>#define?__DEBUG__#ifdef?__DEBUG__ #define?DEBUG(format,...)?printf("Date:?"__DATE__",File:?"__FILE__",?Line:?%05d:?"format"\n",?__LINE__,?##__VA_ARGS__) #else #define?DEBUG(format,...) #endifint?main(int?argc,?char?**argv)?{char?str[]="Hello?World";DEBUG("%s",str);return?0; }

?

輸出如下

Date:?Oct??5?2018,File:?/code/main.c,?Line:?00013:?Hello?World sandbox>?exited?with?status?0

?

在線編譯器網址:https://tool.lu/coderunner/

?

?4 ## __VA_ARGS__ ... 宏和可變參數

在GNU C中,宏可以接受可變數目的參數,就象函數一樣

例如:?

#define?pr_debug(fmt,arg...)?\? printk(KERN_DEBUG?fmt,?##arg)

用可變參數宏(variadic macros)傳遞可變參數表?
你可能很熟悉在函數中使用可變參數表,如:

void?printf(const?char*?format,?...);

直到最近,可變參數表還是只能應用在真正的函數中,不能使用在宏中。

C99編譯器標準允許你可以定義可變參數宏(variadic macros),這樣你就可以使用擁有可以變化的參數表的宏。可變參數宏就像下面這個樣子:

#define?debug(...)?printf(__VA_ARGS__)

缺省號代表一個可以變化的參數表。使用保留名 __VA_ARGS__ 把參數傳遞給宏。當宏的調用展開時,實際的參數就傳遞給 printf()了

例如:?

debug("Y?=?%d\n",?y);

而處理器會把宏的調用替換成:?

printf("Y?=?%d\n",?y);

因為debug()是一個可變參數宏,你能在每一次調用中傳遞不同數目的參數:?

debug("test");//?一個參數

用GCC和C99的可變參數宏, 更方便地打印調試信息
可變參數宏不被ANSI/ISO C++ 所正式支持。因此,你應當檢查你的編譯器,看它是否支持這項技術。?

可變參數的宏里的'##'操作說明帶有可變參數的宏(Macros with a Variable Number of Arguments)?

更詳細請查看如下鏈接

http://www.cnblogs.com/alexshi/archive/2012/03/09/2388453.html

?

?5 舉個栗子-Linux內核調試宏

?

下面是Android touchscreen驅動的調試宏用法,看這樣的寫法就是一個大神了,給大家借鑒。

//?Log?define #define?GTP_ERROR(fmt,arg...)??????????printk("<<-GTP-ERROR->>?"fmt"\n",##arg) #if?DEBUG_SWITCH #define?GTP_INFO(fmt,arg...)???????????printk("<<-GTP-INFO->>?"fmt"\n",##arg) #define?GTP_DEBUG(fmt,arg...)??????????do{\if(GTP_DEBUG_ON)\printk("<<-GTP-DEBUG->>?[%d]"fmt"\n",__LINE__,?##arg);\}while(0) #define?GTP_DEBUG_ARRAY(array,?num)????do{\s32?i;\u8*?a?=?array;\if(GTP_DEBUG_ARRAY_ON)\{\printk("<<-GTP-DEBUG-ARRAY->>\n");\for?(i?=?0;?i?<?(num);?i++)\{\printk("%02x???",?(a)[i]);\if?((i?+?1?)?%10?==?0)\{\printk("\n");\}\}\printk("\n");\}\}while(0) #define?GTP_DEBUG_FUNC()???????????????do{\if(GTP_DEBUG_FUNC_ON)\printk("?????<<-GTP-FUNC->>???????Func:%s@Line:%d\n",__func__,__LINE__);\}while(0)#else #define?GTP_INFO(fmt,arg...) #define?GTP_DEBUG(fmt,arg...) #define?GTP_DEBUG_ARRAY(array,?num) #define?GTP_DEBUG_FUNC() #endif

?

?


?

歡迎加我微信(weiqifa0)拉大家進微信技術討論群

?

?

歡迎關注微信公眾號-嵌入式Linux

?

總結

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

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