在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 )