在我们使用函数时,一般大多数情况下里面的参数都是给定的,而且我们一般使用时并不会超过三个参数,可是这并不排除不会出现三个以上的参数,比如说求平均值,求和等等一些可能出现三个以上参数的函数运算,这时我们的参数不再是固定的,而是随时会不断变化的。因此我们就需要一种方法来实现它们,这种方法就是C语言给我们提供的一种叫做可变参数列表的函数方法。

  首先,可变参数列表是通过来定义的,而这些宏又在<stdarg.h>的头文件中,因此我们在使用时要先引用该头文件,在引用后我们需要其下三个宏的函数:

void va_start(va_list ap, last);
type va_arg(va_list ap, type);
void va_end(va_list ap);

上面这三个函数都是用宏定义的,下面是这些宏在标准ANSI形式下的定义:

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实际上是一个字符类型的指针。

_INTSIZEOF()这个函数主要是把传进来n的长度变成int长度的整数倍。

va_start主要作用是将va_list定义的指针指向v后面的地方,也就是可变参数第一个数的首地址,实际上就是对va_list进行初始化。

va_arg则是将当前参数取出并将va_list定义的指针变量指向下一个参数,t指的是参数类型。

va_end是对整个参数列表进行清理或者也可理解为释放。

  下面通过一个简单的例子看下具体的实现方法---通过可变参数列表实现求多个数的最大值

#include<stdarg.h>
int MAX(int count,...)
{
    int i=0;
    int max=0;
    int k=0;
    va_list arg;   //定义一个va_list类型的变量
    va_start(arg,count);  //让arg指向count后面第一个可变参数,进行初始化
    max=va_arg(arg,int);  //将第一个可变参数取出,并指向下一个可变参数
    for(i=0;i<count-1;i++)
    {
      k=va_arg(arg,int);  //通过count依次取出
      if(k>max)          //进行比较
      max=k;
    }
    va_end(arg);   //进行清理释放
    return max;
}

这就是C中可变参数的用法,我们的printf,scanf等都是通过它们实现的,当然有一点要注意的是可变参数列表可接受多个参数,但至少需要一个参数。