在stdarg.h中有这样一些宏,他们实现了神奇的可变参数,即参数个数不定,我们日常使用的printf就是利用这种技术实现的。
下面先看一段程序。
#include <iostream> #include <stdarg.h> using namespace std; int print_args(int begin,...) { va_list ap;//整个参数列表 char *p = NULL; int n; va_start(ap,begin);//从参数列表的第一个参数开始遍历 p = va_arg(ap,char *); n=0; while(p != NULL) { n++; printf("arg %d:%s\n",n,p); p = va_arg(ap,char *); } va_end(ap); return n; } int main() { int n; n = print_args(-1,"hello","world",NULL); printf("first,without NULL:%d\n",n); n = print_args(-1,"China","beijing","Olympic",NULL); printf("second,without NULL : %d \n",n); return 0; }
输出结果为:
arg 1:hello
arg 2:world
first,without NULL:2
arg 1:China
arg 2:beijing
arg 3:Olympic
second,without NULL : 3
请按任意键继续. . .
里面有几个宏,我们来“转到定义”一下
va_list 来自于typedef char * va_list; (vadefs.h)
va_start 来自于 #define va_start _crt_va_start (stdarg.h)
而_crt_va_start 来自于 #define _crt_va_start(ap,v) ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) ) ----vadefs.h
va_arg 来源于 #define va_arg _crt_va_arg
而_crt_va_arg 来源于 #define _crt_va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
va_end 来源于 #define va_end _crt_va_end
而_crt_va_end 来源于#define _crt_va_end(ap) ( ap = (va_list)0 )