有时我们需要编写这样的函数:函数的参数个数不确定,就像printf(const char* szFormat, ...);一样。这时候,如何方便地处理这些变参是一件需要仔细考虑的问题,例如我们需要在函数中判断用户输入的参数中是否有等于0的实参,你该怎么做?
幸运的时,大师级的先驱们已经为我们做好了,下面让我们一起来研究一下va_arg, va_end,va_start等相关的用法吧!<参看MSDN>
1、需要的头文件和库文件
ANSI 版(windows下):
<stdio.h>和<stdarg.h>
UINX 版
<varargs.h>
库文件:
单线程静态库:LIBC.LIB
多线程静态库:LIBCMT.LIB
MSVCRT.DLL的导入库:MSVCRT.LIB
2、鉴于学习的window,暂时不考虑UINX版
在stdarg.h中:关于va_list的定义如下:
关于va_start, va_end, va_arg的定义如下:
3、MSDN中关于va_start,va_end,va_arg的描述
type va_arg(va_list arg_ptr, type);
void va_end(va_list arg_ptr);
void va_start(va_list arg_ptr, prev_param);(ANSI版)
type 为接收的参数的类型
arg_ptr 为指向参数列表的指针
prev_param 为 原始参数列中最前面的(第一个)参数。
va_start宏:设置参数列表指针arg_ptr指向传递给函数参数表的第一个原始参数(prev_param)
va_end宏:在所有参数被检索完成后,va_end重置指针arg_ptr指向NULL
va_arg宏:接收arg_ptr指向的type类型的变量,同时使arg_ptr加一,指向参数列表的下一个变量,它是通过宏中的第二个参数type来确定下一个变量的开始位置,va_arg可以在函数中使用任意多次来接收参数列表中的参数。
4、用例:
#include <stdio.h>
#define ANSI
#ifdef ANSI
#include <stdarg.h>
//声明一个变参函数
int average(int first, ...);
#endif
int average(int first, ...)
{
int count =0, sum =0, i= first;
va_list m_args;//定义自己的参数列表指针
va_start(m_args, first);//使参数列表指针指向输入参数表的第一个//参数
while(i != -1)
{
sum+=i;
count++;
i = va_arg(m_args, int);//取出当前参数
}
va_end(m_args);//置空列表指针,以便下一次使用
return( sum?(sum/count):0);
}
int main(int crgc, char** argv)
{
printf("%d", average(1, 2, -1));
printf("%d", average(1, 2, 3, -1));
printf("%d", average(1, 2, 3, 4, -1));
}