可变参数列表式通过宏来实现的,宏定义在 stdarg.h头文件中,该头文件声明了一个类型va_list 和三个宏 。
 
提供的三个宏分别如下:
void va_start(va_list ap, last);
type va_arg(va_list ap, type);
void va_end(va_list ap);
这种隐式的数据类型是va_list 
上面宏的前缀va表示variable argument,即可变参数的意思。变量ap专门用来记录获取可变参数。下面依次介绍三个宏的意义和用法。
[*] void va_start( va_list ap, last)
        last为函数形参中"..."前的最后一个形参名字,宏va_start用于根据last的位置(或指针)来初始化变量ap,以供宏ar_arg来依次获得可变参数的值。变量ap在被va_argva_end使用前,必须使用va_start初始化。
[*] type va_arg(va_list ap, type)

       va_arg宏用来获得下一个参数的值,type为该参数的类型,它的参数ap必须被va_start初始化,通过该宏后,返回参数值并使用ap指向下一个参数,以供va_arg再次使用。如果没有下一个参数时调用va_argarg指定的类型不兼容时,会产生可知的错误。

[*]void va_end(va_list ap)

         va_endva_start必须要同一函数里面对称使用,调用va_start(ap,last)ap得到初始化,在完成参数处理后,需要调用va_end(ap)释放”ap   

 

下面我们来探讨如何写一个简单的可变参数的C函数.写可变参数的
C函数要在程序中用到以下这些宏:
void va_start( va_list arg_ptr, prev_param );

type va_arg( va_list arg_ptr, type );

void va_end( va_list arg_ptr );
va在这里是variable-argument(可变参数)的意思.
这些宏定义在stdarg.h中,所以用到可变参数的程序应该包含这个
头文件.下面我们写一个简单的可变参数的函数,改函数至少有一个整数
参数,第二个参数也是整数,是可选的.函数只是打印这两个参数的值.
void simple_va_fun(int i, ...)
{
va_list arg_ptr;
int j=0;

va_start(arg_ptr, i);
j=va_arg(arg_ptr, int);
va_end(arg_ptr);
printf("%d %d\n", i, j);
return;
}
我们可以在我们的头文件中这样声明我们的函数:
extern void simple_va_fun(int i, ...);
我们在程序中可以这样调用:
simple_va_fun(100);
simple_va_fun(100,200);
从这个函数的实现可以看到,我们使用可变参数应该有以下步骤:
1)首先在函数里定义一个va_list型的变量,这里是arg_ptr,这个变
量是指向参数的指针.
2)然后用va_start宏初始化变量arg_ptr,这个宏的第二个参数是第
一个可变参数的前一个参数,是一个固定的参数.
3)然后用va_arg返回可变的参数,并赋值给整数j. va_arg的第二个
参数是你要返回的参数的类型,这里是int型.
4)最后用va_end宏结束可变参数的获取.然后你就可以在函数里使
用第二个参数了.如果函数有多个可变参数的,依次调用va_arg获
取各个参数.
如果我们用下面三种方法调用的话,都是合法的,但结果却不一样:
1)simple_va_fun(100);
结果是:100 -123456789(会变的值)
2)simple_va_fun(100,200);
结果是:100 200
3)simple_va_fun(100,200,300);
结果是:100 200
我们看到第一种调用有错误,第二种调用正确,第三种调用尽管结果
正确,但和我们函数最初的设计有冲突.下面一节我们探讨出现这些结果
的原因和可变参数在编译器中是如何处理的.