1. 程式人生 > >LINUX C中如何定義可變引數的巨集

LINUX C中如何定義可變引數的巨集

轉載:http://darksun.blog.51cto.com/3874064/1379569

一般在除錯列印Debug資訊的時候, 需要可變引數的巨集. 從C99開始可以使編譯器標準支援可變引數巨集(variadic macros), 另外GCC也支援可變引數巨集, 但是兩種在細節上可能存在區別.
1. __VA_ARGS__
__VA_ARGS__ 將 "..." 傳遞給巨集 . 如

#define debug1(...) fprintf(stderr, __VA_ARGS__)
#define debug2(format, ...) fprintf(stderr, format, __VA_ARGS__)


2. GCC的複雜巨集

GCC使用一種不同的語法,從而可以給可變引數一個名字,如同其它引數一樣.
#define debug1(args...) fprintf(stderr, args)  
#define debug2(format, args...) fprintf(stderr, format, args) 
這和第一條的巨集例子是完全一樣的,但是這麼寫可讀性更強並且更容易進行描述.

3. ##__VA_ARGS__,  ##args
上面兩個定義的巨集,如果出現 debug2("A Message")的時候,由於巨集展開後有個多餘的逗號,所以將導致編譯錯誤.

為了解決這個問題,CPP 使用一個特殊的"##"操作,格式如下:

#define debug3(format, ...) fprintf(stderr, format, ##__VA_ARGS__)
#define debug3(format, args...) fprintf(stderr, format, ##args) 
這裡,如果可變引數被忽略或為空,"##"操作將使前處理器(preprocessor)去除掉它前面的那個逗號.

舉例:
    debug1("t1");     // print "t1"
    debug2("t2");     // compile error(gcc but vs)
    debug2("t%d", 2); // print "t2"
    debug3("t3");     // print "t3"
    debug3("t%d", 3); // print "t3"