可變參數巨集(DEBUG)

来源:http://www.cnblogs.com/yujone/archive/2016/02/27/5222843.html
-Advertisement-
Play Games

之前一直是到處寫printf來列印調試信息,不需要是還得一個一個註釋掉.之後上網查詢發現有很多方法來進行DEBUG列印,參數可變而且方便一次性開關. #define DEBUG(fmt,...) printf (fmt,lxx_va_args) 這裡的“…”指的是可變參數. int main() {...


之前一直是到處寫printf來列印調試信息,不需要是還得一個一個註釋掉.之後上網查詢發現有很多方法來進行DEBUG列印,參數可變而且方便一次性開關.

#define DEBUG(fmt,...)    printf (fmt,__VA_ARGS__)        這裡的“…”指的是可變參數.

int main() { DEBUG(“hello %d”,10); return 0; }

有時候,有個模塊有輸出信息,錯誤信息等.如果想單獨打開某一部分,可以如此設計:

  1: #define DRV_DEBUG       1
  2: #define DRV_DEBUG_IN    0x0001
  3: #define DRV_DEBUG_OUT   0x0002
  4: #define DRV_DEBUG_ERR   0x0004
  5: #define DRV_DEBUG_ALL   0xFFFF
  6: #if DRV_DEBUG
  7:      unsigned int drv_flags = DRV_DEBUG_ERR | DRV_DEBUG_OUT;
  8:      #define DRV_PRINT(flag, fmt, …)        \
  9:        do{                                  \
 10:            if (drv_flags & flag){           \
 11:                 printf(fmt, __VA_ARGS__);}  \
 12:            }while(0)
 13: #else
 14: #define DRV_PRINT(fmt,…)
 15: #endif
 

這樣,我只要列印OUT和ERR:

  1: void drv_write(char * msg_out)
  2: {
  3: 	DRV_PRINT(DRV_DEBUG_OUT,"%s", msg_out);		//輸出
  4: 	DRV_PRINT(DRV_DEBUG_ERR,"%s", msg_out);		//輸出
  5: 	DRV_PRINT(DRV_DEBUG_IN,"%s", msg_out);		//不輸出
  6: }
進一步,可以設計針對整個系統不同模塊的LOG輸出控制!TCP/IP協議棧實現Lwip就是這麼乾的.
但是發現光有printf還不夠,雖然調試信息是出來了,但是在這麼多的調試信息中並不能一下子知道這信息是從哪裡列印出來的.所以查到用另一種方法可以將文件名和源碼位置都列印出來.
在ANSI C中有這樣幾個巨集
__LINE__:插入當前行號
__FILE__:插入當前原文件名
__DATE__:插入當前編譯日期
__TIME__:插入當前編譯時間
所以巨集就變成這樣子了DEBUG(fmt,…)    printf(“FILE:”__FILE__”“,LINE:%d:”fmt”\n”,__LINE__,##__VA_ARGS__)
這裡特別註意下##__VA_ARGS__這裡的##是很有必要的,因為他的意思是如果沒有參數則讓預處理器忽略前面一個逗號.上面第一段的寫法不加參數是出錯的.所以第一段寫法必須帶參數.
DRV_PRINT(DRV_DEBUG_OUT,“hello world”);		//有問題,需要更改巨集定義,在前加上##

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 事主的問題應該是想把最新的數據和次新數據放在一行里顯示。 因為沒有說明重覆的情況如何處理,即有多個最新數據或者有多個次新數據,所以我沒有做過多的處理。 哈哈哈。
  • 簡介 什麼是死鎖? 我認為,死鎖是由於兩個對象在擁有一份資源的情況下申請另一份資源,而另一份資源恰好又是這兩對象正持有的,導致兩對象無法完成操作,且所持資源無法釋放。 什麼又是阻塞? 阻塞是由於資源不足引起的排隊等待現象。比如同時兩個進程去更新一個表。 這裡我們可以把阻塞作為死鎖的必要條件。下麵我們
  • 教程:http://jingyan.baidu.com/article/f3ad7d0ffc061a09c3345bf0.html Mysql修改設置root密碼的命令及方法:http://jingyan.baidu.com/article/a3f121e41b141afc9052bb8e.html
  • 資料庫是定義及產品分類
  • SQL
    一.Transact-SQL的GO,詳解 (1) SQL Server 實用工具將 GO 解釋為應將當前的 Transact-SQL 批處理語句發送給 SQL Server 的信號。當前批處理語句是自上一 GO 命令後輸入的所有語句,若是第一條 GO 命令,則是從特殊會話或腳本的開始 處到這條 GO
  • SQL Server代理是所有實時資料庫的核心。代理有很多不明顯的用法,因此系統的知識,對於開發人員還是DBA都是有用的。這系列文章會通俗介紹它的很多用法。 在這一系列的上一篇,我們查看了維護計劃,一個維護計劃可能會創建多個作業,多個計劃。你還簡單地看了SSIS子系統,並查看了維護計劃作業步驟的 屬
  • 最近項目中要遞歸樹形,案例如下: 測試數據: CREATE TABLE tb(ID char(3),PID char(3),Name nvarchar(10)) INSERT tb SELECT'001',NULL ,'山東省' UNION ALL SELECT'002','001','煙臺市' U
  • 為數據表去掉一個外鍵關聯,然後再添加一個外鍵關聯.批量數據導入.在全部用戶表和存儲過程中尋找包含某段文字的用戶表和存儲過程.數據表的列重命名.
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...