在c語言的標準庫中,printf、scanf、sscanf、sprintf、sscanf這些標準庫的輸入輸出函式,引數都是可變的。在除錯程式時,我們可能希望定義乙個引數可變的輸出函式來記錄日誌,那麼用可變引數的巨集是乙個不錯的選擇。
在c99中規定巨集也可以像函式一樣帶可變的引數,如:
#define log(format, ...) fprintf(stdout, format, __va_args__)
其中,...表示可變引數列表,__va_args__在預處理中,會被實際的引數集(實參列表)所替換。
同時gcc還支援帶可以變引數名的方式(注意:vc不支援):
#define log(format, args...) fprintf(stdout, format, args)
同樣,args在預處理過程中,會被實際的引數集所替換。其用法和上面的方式一樣,只是引數的符號有變。
需要注意的是,上述兩種方式的可變引數不能省略,儘管可以傳乙個空引數進去。說到這裡,有必要提一下「##」連線符號的用法,「##」的作用是對token進行連線,上例中format,args,__va_args都可以看作是token,如果token為空,「##」則不進行連線,所以允許省略可變引數。對上述2個示例的改造:
#define log(format, ...) fprintf(stdout, format, ##__va_args__)
#define log(format, args...) fprintf(stdout, format, ##args)
即然引數可以省略,那麼用巨集定義乙個開關,實現乙個輸出日誌的函式就簡單了:
#ifdef debug
#define log(format, ...) fprintf(stdout, ">>>>>" format "<<<<", ##__va_args__)
#else
#define log(format, ...)
#endif
#include "stdio.h"
#define log_type1(format, ...) do while(0)
#define log_type2(format, args...) do while(0)
#define log_type3(format, ...) do while(0)
#define log_type4(format, args...) do while(0)
#define log(x) printf("log "#x" %d \n", x);
int value = 10;
int main()
C 語言 define 變參 VA ARGS
在c語言的標準庫中,printf scanf sscanf sprintf sscanf這些標準庫的輸入輸出函式,引數都是可變的。在除錯程式時,我們可能希望定義乙個引數可變的輸出函式來記錄日誌,那麼用可變引數的巨集是乙個不錯的選擇。在c99中規定巨集也可以像函式一樣帶可變的引數,如 define l...
C語言變參使用
c語言中有很多變參的使用,例如printf 的原型是int printf const char fmt,那麼c語言是如何解析和處理這些變參的呢?下面進行簡單的總結 c語言中定義了下面的一些巨集,專門用來處理變參 va start va list ap,char fmt va arg va list ...
C語言(變參函式)
c語言雖然沒有c 的函式過載特性,但也可以實現變參,但要保證第乙個引數資訊的完整性。拓展 定義變參函式時,第乙個引數一般是字串,攜帶後續變參的型別和數量資訊,變參使用三點來表示,如 void sumup const char info,再使用va list va start va arg 和va e...