臥槽,自定義打印函數還能這么完?
剛開始學習串口的時候,為了更好的格式化輸出數據,一般會選擇重定向 printf 函數,即使用 printf 打印到串口,這個是很多初學者都知曉的事情,網上也有一大堆資料可查。
絕大多數重定向方法都是采用串口查詢方式,所以打印效率很低,也不適合在中斷中打印(因為速度太慢了,影響中斷執行)。
后來,不滿足于簡單重定向,開始利用 C 庫函數自己實現打印函數,這個時候,我們會充分利用資源,比如 DMA、內存等加快我們的打印,這個時候,打印幾百字節只需要微秒級別的時間即可(主要是內存搬運耗時)。
所以魚鷹實現了一個 DMA 方式的自定義 printf 函數,使得整個項目的效率大大提高(這個以后有時間再寫,內容比較多)。
對此魚鷹是相當滿意的。但有一個點讓魚鷹非常不舒服。
我們知道,在 MDK 中使用 printf 函數時,如果出現格式不對或者類型不匹配,編譯的時候會出現警告之類的,如下:
總之,編譯器能幫助我們避免一些低級錯誤(即使老司機也可能會犯)。
但是,自定義的打印函數卻沒有這種功能,比如魚鷹這個簡單的:
int my_printf(const char *fmt, ...) { return 0; }
使用時,即使有問題,也不會有任何警告提示:
再比如 RT-Thread 中實現的 rt_kprintf, 使用時同樣如此。
原以為,魚鷹實現的自定義打印函數只能帶著這樣的遺憾繼續使用,但最近魚鷹卻偶然了解到有一個神奇的東東可以解決這個問題。
它就是魚鷹曾經介紹過的屬性設置 __attribute__ :
__attribute__ ((format (printf, 1, 2))) // 按 printf 函數的格式
只是魚鷹當時不知道它還能這么玩,只要自定義打印函數加上這個聲明,就可以完美解決上述無警告的問題。
比如這樣:
如此一來,我們的自定義函數也可以像 printf 函數一樣,提前將一些低級錯誤提示出來了(除了左邊感嘆號,編譯的時候也有警告)。
這才是完美的自定義打印函數呀,大家趕快試一試吧。
*博客內容為網友個人發布,僅代表博主個人觀點,如有侵權請聯系工作人員刪除。