首先要应用可变参数列表需要加头文件#include<stdarg.h>,可变参数列表是通过宏来实现的,这些宏定义在头文件中。
现在模拟实现printf函数
void print(const char *format,...) //至少含有一个参数
{
va_list arg; //va_list是char*的重命名
va_start(arg,format);
while(*format)
{
switch(*format)
{
case'c':
{
char tmp=va_arg(arg,char);
putchar(tmp);
}
break;
case 's':
{
char*str=va_arg(arg,char*);
while(*str)
{
putchar(*str);
str++;
}
}
break;
default:
putchar(*format);
break;
}
format++;
}
va_end(arg);
}
int main()
{
print("s cccc.\n","hello",'w','o','r','d');
system("pause");
return 0;
}
函数声明了一个变量va_arg,用来访问可变参数列表未确定的部分。va_start来初始化这个变量,第一个参数是va_list创建变量的名字,第二个参数是省略号前的参数。初始化过程是使va_arg指向可变参数部分的第一个参数。
//va_arg(arg,char)//访问参数时需使用va_arg,第一个参数是va_list变量,第二个参数是参数列表中下一个参数的类型。
//va_end(arg)//把arg赋成NULL
这几个宏转到定义处为:
va_list typedef char* va_list
va_start #define va_start _crt_va_start 再转到定义处为#define _crt_va_start(ap,v) ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) ) 作用是让指针arg找到第一个可变参数
va_arg #define _crt_va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
va_end #define _crt_va_end(ap) ( ap = (va_list)0 )
总结:
可变参数列表是通过宏来实现的,宏无法判断参数的类型和个数,所以需使用命名参数。