用到了以下三个宏(第四个宏只是与之相关,并没用到):
void va_start(va_list arg_ptr, prev_param);
type va_arg(va_list arg_ptr, type);
void va_end(va_list arg_ptr);
void va_copy(va_list d, va_list s);
va_list:用来保存宏va_start、va_arg和va_end所需信息的一种类型。为了访问变长参数列表中的参数,必须声明va_list类型的一个对象,它的定义:
typedef char * va_list;
va_start:访问变长参数列表中的参数之前使用的宏,它初始化用va_list声明的对象,初始化结果供宏va_arg和va_end使用;
va_arg: 展开成一个表达式的宏,该表达式具有变长参数列表中下一个参数的值和类型。每次调用va_arg都会修改用va_list声明的对象,从而使该对象指向参数列表中的下一个参数;
va_end:该宏使程序能够从变长参数列表用宏va_start引用的函数中正常返回。
下面是示例代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdarg.h> 4 5 /* ANSI标准形式的声明方式,括号内的省略号表示可选参数 */ 6 int demo(char *msg, ...) 7 { 8 va_list arg_list = NULL; // 定义保存函数参数的结构,实际上是字符串 9 int count = 0; // 纪录参数个数 10 char* para = NULL; // 存放取出的字符串参数 11 12 /* argp指向传入的第一个可选参数,msg是最后一个确定的参数 */ 13 va_start(arg_list, msg); 14 15 while (1) 16 { 17 /* 取出当前的参数,类型为char* */ 18 /* 一般自定的变长参数函数,变长部分类型都是统一的 */ 19 /* 如果想编写类似与printf这种参数类型不固定的变长参数的函数 */ 20 /* 那么就需要在参数中说明参数的类型,例如%d表示整数,%s表示字符串 */ 21 para = va_arg(arg_list, char *); 22 23 /* 采用空串指示参数输入结束,这是必须,函数需要知道参数列表的结尾 */ 24 if (0 == strcmp(para, "\0")) 25 { 26 break; 27 } 28 29 printf("Parameter #%d is: %s\n", count, para); 30 count++; 31 } 32 33 /* 完成清理工作 */ 34 va_end(arg_list); 35 36 return 0; 37 } 38 39 int main(void) 40 { 41 demo("DEMO", "This is a demo!", "You are so cute ^_^!", "\0"); 42 43 return 0; 44 } 45 46 /* 47 输出结果: 48 Parameter #0 is: This is a demo! 49 Parameter #1 is: You are so cute ^_^! 50 */