早上開啟郵箱,在訂閱的郵件列表裡發現了乙個關於可變引數的討論,剛好前幾天用過它,於是進去看了看,獲益匪淺。收集整理如下,以備中文引擎查詢。
原討論位址如下:http://groups.google.com/group/comp.lang.c/browse_thread/thread/f18fb0c39479c1c5/ec2b90d212d8caa1?hl=zh-cn#ec2b90d212d8caa1
在c99編譯器標準中,允許定義可變引數巨集(variadic macros),而此前,可變參數列還只能應用在真正的函式中。
以下就是收集來的一組非常有用的巨集,使用它可以得到可變引數的數目(注:vc並不支援c99標準,所以無法編譯該巨集!而我在linux下使用gcc成功驗證了該巨集的正確性。)
源自:http://groups.google.com.au/group/comp.std.c/browse_thread/thread/77ee8c8f92e4a3fb?hl=en
/***將以下巨集新增入你的**中**/
#define pp_narg(...) /
pp_narg_(__va_args__,pp_rseq_n())
#define pp_narg_(...) /
pp_arg_n(__va_args__)
#define pp_arg_n( /
_1, _2, _3, _4, _5, _6, _7, _8, _9,_10, /
_11,_12,_13,_14,_15,_16,_17,_18,_19,_20, /
_21,_22,_23,_24,_25,_26,_27,_28,_29,_30, /
_31,_32,_33,_34,_35,_36,_37,_38,_39,_40, /
_41,_42,_43,_44,_45,_46,_47,_48,_49,_50, /
_51,_52,_53,_54,_55,_56,_57,_58,_59,_60, /
_61,_62,_63,n,...) n
#define pp_rseq_n() /
63,62,61,60, /
59,58,57,56,55,54,53,52,51,50, /
49,48,47,46,45,44,43,42,41,40, /
39,38,37,36,35,34,33,32,31,30, /
29,28,27,26,25,24,23,22,21,20, /
19,18,17,16,15,14,13,12,11,10, /
9,8,7,6,5,4,3,2,1,0
/***
*使用巨集pp_narg(...)即可得到可變引數的個數。如下:**/
pp_narg(a) -> 1
pp_narg(a,b) -> 2
pp_narg(a,b,c) -> 3
pp_narg(a,b,c,d) -> 4
pp_narg(a,b,c,d,e) -> 5
pp_narg(1,2,3,4,5,6,7,8,9,0,
1,2,3,4,5,6,7,8,9,0,
1,2,3,4,5,6,7,8,9,0,
1,2,3,4,5,6,7,8,9,0,
1,2,3,4,5,6,7,8,9,0,
1,2,3,4,5,6,7,8,9,0,
1,2,3) -> 63
對於不支援c99標準的編譯器,如vc,還是用函式來實現吧,技巧就在於使用乙個null代表可變引數的結束。(注:這個null的安全使用方法就是加上修飾,比如說(void*)null、(char*)null或者其它型別,這觀點存在於討論中)然後,將所有可變引數讀入va_list中,用va_arg逐一獲取引數,直至出現null為止。大家可以在msdn上找到示例,該示例讀取的int引數,並以-1作為結束標誌。
可變引數及可變引數巨集的使用
我們在c語言程式設計中會遇到一些引數個數可變的函式,例如printf 這個函式,這裡將介紹可變函式的寫法以及原理.一般在除錯列印debug 資訊的時候,需要可變引數的巨集.從c99開始可以使編譯器標準支援可變引數巨集 variadic macros 另外gcc 也支援可變引數巨集,但是兩種在細節上可...
GCC 可變引數的巨集
標準 c只支援可變引數的函式,意味著函式的引數是不固定的,例如printf 函式 的原型為 int printf const char format argument 而在gnu c中,巨集也可以接受可變數目的引數,例如 define pr debug fmt,arg.printk fmt,arg ...
可變引數的巨集定義
link todo 原理 printf 和fprintf 這些輸出函式的引數是可變的,在除錯程式時,你可能希望定義自己的引數可變的輸出函式,那麼可變引數巨集會是乙個選擇。c99中規定巨集可以像函式一樣帶有可變引數,比如 define log format,fprintf stdout,format,...