函數原型: int printf(const char *format[,argument]...)
返 回 值: 成功則返回實際輸出的字符數,失敗返回-1.
函數說明:
在printf()函數中,format後面的參數個數不肯定,且類型也不肯定,這些參數都存放在棧內.調用printf()函數時,根據format裏的格式("%d %f...")依次將棧裏參數取出.而取出動做要用到va_arg、va_end、va_start這三個宏定義,再加上va_list.
(1)va_list事實上是一char *類型,即:
typedef char* va_list;
(2)三個宏定義:
#define _INTSIZEOF(n) ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
#define va_arg(ap,type) ( *(type *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define va_end(ap) ( ap = (va_list)0 )
【attention】c語言中可變參數的原理---printf()函數
int printf(const char* format,...);
使用過C語言的人所再熟悉不過的printf函數原型,它的參數中就有固定參數format和可變參數(用」…」表示).而程序員又能夠用各類方式來調用printf,如:
printf("%d ",value);
printf("%s ",str);
printf("the number is %d,string is:%s ",value,str);
能夠看出,該函數的參數格式不固定,參數類型不固定.在C語言中使用宏來處理這些可變參數.這些宏看起來很複雜,其實原理挺簡單,即根據參數入棧的特色從最靠近第一個可變參數的固定參數開始,依次獲取每一個可變參數的地址.
(1)宏va_start
經過該宏定義能夠獲取到可變參數表的首地址,並將該地址賦給指針ap.
(2)宏va_arg
經過該宏定義能夠獲取當前ap所指向的可變參數,並將指針ap指向下一個可變參數.注意,該宏的第二個參數爲類型.
(3)宏va_end
經過該宏定義能夠結束可變參數的獲取. 程序員
程序員經過這三個宏定義就能夠實現對可變參數的處理.例如: app
C99就支持可變參數宏 ,兩種寫法: 函數
#define dbgprint(format,args...) \
fprintf(stderr, format, ##args)
#define dgbmsg(fmt,...) \
printf(fmt,__VA_ARGS__) spa