2014-03-10 21:40 仅出于方便使用的目的,错误不可避免,请见谅。
翻译自:the c book : variable number of arguments
- 经常需要实现这样一种函数:参数个数未知或者参数个数不确定,比如printf。下面的例子将展现此类函数的声明/定义及使用。
int f(int , ……);
int f(int,……) {……};
int g() { f(1,2,3);}
- 如何访问可变参数?
需要包含头文件<stdarg.h>。其中,引入了一种新的类型va_list,同时声明了va_start,va_arg,var_end。
void va_start(va_list ap, parmN);
type va_arg(va_list ap, type);
void va_end(va list ap);
首先,需要使用va_start宏来初始化ap,以便接下来供va_arg和va_end来使用。va_start的第二个参数,即parmN是可变参数函数声明中最右边的 已命名形成变量标识符(在‘……’之前的变量标识符)。注意:parmN不可以是:register存储类型变量,函数,数组类型。其次,ap初始化以后,可以通过va_arg宏来访问参数。每一次调用va_arg都会从参数列表中抽取出“下一个参数”,并以指定类型返回该参数。如果“下 一个参数”不是指定类型的变量,这行为未定义。需要注意避免由“算术转换arithmetic conversions”带来的问题。使用char或者short作为va_arg的第二参数,不可避免的招致错误,因为这些类型,通常会被“提升“至signed int
或者unsigned int;同样地,float将会被转换为double。
注意,对于类型
char
,unsigned char
,unsigned short
和 unsigned bitfields都将被“提升”至unsigned int。
对于没有更多的参数可用时,调用va_arg将导致未定义行为。参数type需满足这样的要求:通过附加一个*,即可转换为相应类型的指针类型。比如,char附加*后,即为char *;char []就不能满足要求。
最后,当所有参数都被处理结束后,需要调用va_end,以避免va_list被继续使用,若是没有使用va_end,则会有未定义行为。
整个 参数列表,在再次调用va_start后,可以被再次重新遍历使用。
/*just a demo*/
#include <stdarg.h>
#include <stdio.h>
int maxof(int,int, ...) ;
void f(void);
int main()
{
f();
exit(EXIT_SUCCESS);//cstdlib中定义的宏
}
int maxof(int aa,int n_args, ...)
{
register int i;
int max, a;
va_list ap;
va_start(ap, n_args);
max = va_arg(ap, int);//获取n_args后的第一个参数
printf("%d\n",max);
for(i = 2; i <= n_args; i++) {
if((a = va_arg(ap, int)) > max)
max = a;
}
va_end(ap);
return max;
}
void f(void)
{
int i = 5;
int j[256];
j[42] = 1;
printf("%d\n",maxof(1,3, i, j[42], 0));
}