在C/C++中,提起“宏”多少有些皺眉,至少我在入門C++時旁人好心提醒:盡可能地使用typedef與const常量定義來替代“宏”的使用:
1. 類型宏定義
#define HANLE void*
//可以替換為:
typedef void *HANLE;
2. 常量定義
#define MAX_LIMIT 4096
//可以替換為:
const int s_MAX_LIMIT 4096;
因為宏定義是在預編譯階段,對內容進行直接替換,因此無法提供安全的類型檢查等功能。
但我本次要說的是,宏的一個很炫的應用:
配合printf函數能夠方便地自定義輸出格式和內容。
舉例來說吧,就是用戶在程序中調用:
USER_PRINT( "i should checkout: v_a value is %d.\n", value_a );
能夠輸出類似信息
[2013-10-01 15:18:28][Fox Test][PID:2486]i should checkout: v_a value is 10.
當然,如果你用過linux下的syslog,你會發現這條輸出信息算是“高仿”了。syslog可是linux下調試/監控的優秀組件,簡單易用不說,功能也比較完備!
扯遠了,本次的目標就是如何在用戶簡單輸出一條信息的時候,我們能夠同時加上各種附加信息,包括時間/用戶/PID等參數,方便我們的調試/監控。
C++ Primer Plus 第6版 中文版 清晰有書簽PDF+源代碼 http://www.linuxidc.com/Linux/2014-05/101227.htm
讀C++ Primer 之構造函數陷阱 http://www.linuxidc.com/Linux/2011-08/40176.htm
讀C++ Primer 之智能指針 http://www.linuxidc.com/Linux/2011-08/40177.htm
讀C++ Primer 之句柄類 http://www.linuxidc.com/Linux/2011-08/40175.htm
C++11 獲取系統時間庫函數 time since epoch http://www.linuxidc.com/Linux/2014-03/97446.htm
C++11中正則表達式測試 http://www.linuxidc.com/Linux/2012-08/69086.htm
1. 首先,提供一個有意思的宏,該宏也是該功能的核心
#define USER_PRINT_BASE( format, args... ) printf( format, ##args )
是不是看到args...有點兒蒙,以及##args又是鬧哪樣?
說明一下:
i: args...是一個參數,是C/C++中定義變參函數(參數不固定)的一種格式。至於舉個變參函數的例子,printf/scanf什麼的就是隨處可見的例子。
ii: ##args是宏的一個特殊語法應用(和普通的##宏應用不同[TODO]),使得宏展開時可以去掉可能存在的多余的','。
舉例:
當沒有##時,USER_PRINT_BASE( "something debug" )在宏展開時會成為printf( "something debug", )多了一個逗號!
當然,如果你調用USER_PRINT_BASE( "something debug--%d", 10 )的時候,即使沒有'##'也不會出錯。
iii: 如果你的編譯器支持C99規范,那麼宏也可以改寫為:
#define USER_PRINT_BASE( format, ... ) printf( format, ##__VA_ARGS__ )
嗯好吧,其實只是變參的書寫格式發生了點變化。
注:ii與iii詳細的可以參考“C/C++可變參數,“## __VA_ARGS__”宏的介紹和使用”,裡面有很詳細的介紹http://www.linuxidc.com/Linux/2014-06/102923.htm。
更多詳情見請繼續閱讀下一頁的精彩內容: http://www.linuxidc.com/Linux/2014-06/102922p2.htm