可变参数函数指的是函数参数个数不固定的函数,类似printf(char* fmt, …);
如果想自己写一个可变参数的函数,需要用到stdarg.h头文件中的如下几个宏
void va_start( va_list arg_ptr, prev_param );
type va_arg( va_list arg_ptr, type );
void va_end( va_list arg_ptr );
-用法example.c
#include <stdio.h>
#include <stdarg.h>
void myprint(char* fmt, ...)
{
va_list ap;
int d;
char ch, *str;
va_start(ap,fmt);
while(*fmt)
{
switch(*fmt++)
{
case 'd':
d=va_arg(ap, int);
printf("int %d\n", d);
break;
case 's':
str = va_arg(ap, char *);
printf("string %s\n", str);
break;
case 'c':
ch = (char)va_arg(ap, int);
printf("char %c\n", ch);
break;
}
}
va_end(ap);
}
int main()
{
myprint("%d,%s,%d,%s,%c",11,"str1",12,"str2",'@');
return 0;
}
运行结果:
int 11
string str1
int 12
string str2
char @
程序详解
1.首先定义可变参数函数时参数列表中使用(…)代表参数个数不确定,但是一定至少要有一个固定的参数,这里用 的是(char * fmt).
2. 定义va_list ap用来访问未列出的参数
va_list 、va_start、va_arg、va_end的定义如下
typedef char* va_list
#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,t) \
( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define va_end(ap) ( ap = (va_list)0 )
va_list ap定义的ap是一个指针。
va_start(ap,fmt) 将ap初始化赋值,指向第一个未列出的参数。
va_arg 每次返回一个参数的值,并且将ap后移至下一个参数地址
这个结合栈来看会更清晰,C语言的函数是从右至左入栈的,
高地址|-----------------------------|
|函数返回地址 |
|-----------------------------|
|....... |
|-----------------------------|
|第n个参数(第一个可变参数) |
|-----------------------------|<--va_start后ap指向
|第n-1个参数(最后一个固定参数)|
|-----------------------------|<-- &fmt
低地址|-----------------------------|
va_end(ap) 将ap赋值为0,不指向任何地方。
注意:
ch = (char)va_arg(ap, int);
不能使用 ch=(char)va_arg(ap, char);
va_arg(argp, type)宏中不支持的type:
— char、signed char、unsigned char
— short、unsigned short
— signed short、short int、signed short int、unsigned short int
— float
float 用double代替,其他的用 int代替,char* 是可以用的。
参考
[http://blog.csdn.net/weiwangchao_/article/details/4857567]
[http://pcedu.pconline.com.cn/empolder/gj/c/0507/669879_1.html]