va_arg
、、va_copy
va_end
、、va_start
访问变量参数列表。
语法
type va_arg(
va_list arg_ptr,
type
);
void va_copy(
va_list dest,
va_list src
); // (ISO C99 and later)
void va_end(
va_list arg_ptr
);
void va_start(
va_list arg_ptr,
prev_param
); // (ANSI C89 and later)
void va_start(
arg_ptr
); // (deprecated Pre-ANSI C89 standardization version)
参数
type
要检索的参数类型。
arg_ptr
指向参数列表的指针。
dest
指向要从 src
中初始化的参数列表的指针
src
指向要复制到 dest
的参数初始化列表的指针。
prev_param
位于第一个可选实参之前的形参。
返回值
va_arg
返回当前参数。 va_copy
、va_start
和 va_end
不返回值。
备注
函数采用可变数量的参数时,va_arg
、va_copy
、va_end
、和 va_start
宏提供了可移植的方法来访问传递到函数的参数。 有两种版本的宏:STDARG.H
中定义的宏符合 ISO C99 标准;弃用了 VARARGS.H
中定义的宏但是将其保留以保证与写于 ANSI C89 标准之前的代码的后向兼容性。
这些宏假定函数采用固定数量的必需参数,后面是可变数量的可选参数。 将必需参数声明为函数的普通参数,且可通过参数名称访问它们。 可选参数可通过 STDARG.H
中的宏访问(对于在 ANSI C89 标准之前编写的代码,通过 VARARGS.H
),其将指针设置为参数列表中的第一个可选参数、检索列表中的参数并在参数处理完成后重置指针。
STDARG.H
中定义的 C 标准宏使用方法如下:
va_start
将arg_ptr
设置为传递到此函数的参数列表中的第一个可选参数。 参数arg_ptr
必须拥有va_list
类型。 参数prev_param
是紧跟在参数列表中的第一个可选参数之前的必需参数的名称。 如果prev_param
使用注册存储类声明,则不定义宏的行为。 在首次使用va_arg
前必须使用va_start
。va_arg
从arg_ptr
指定的位置中检索type
的值,并增加arg_ptr
以通过使用type
的大小来确定下一个参数的开始位置,来指向列表中的下一个参数。 可以在函数中使用va_arg
任意次,以检索列表中的参数。va_copy
复制当前转态下的参数列表。src
参数必须已使用va_start
进行初始化;可以使用va_arg
调用进行过更新,但是不能使用va_end
进行过重置。va_arg
从dest
中检索到的下一个参数与从src
中检索到的下一个参数相同。检索所有参数后,
va_end
将指针重置为NULL
。 在函数返回前必须在已使用va_start
或va_copy
初始化的各个参数列表上调用va_end
。
注意
VARARGS.H 中的宏已弃用,将其保留只为保证与写于 ANSI C89 标准之前的代码的后向兼容性。 在所有其他情况下,请使用 STDARGS.H 中的宏。
它们使用 /clr
(公共语言运行时编译)编译时,使用这些宏的程序可能会因为本机和公共语言运行时 (CLR) 类型系统之间的差异而生成意外的结果。 考虑此程序:
#include <stdio.h>
#include <stdarg.h>
void testit (int i, ...)
{
va_list argptr;
va_start(argptr, i);
if (i == 0)
{
int n = va_arg(argptr, int);
printf("%d\n", n);
}
else
{
char *s = va_arg(argptr, char*);
printf("%s\n", s);
}
va_end(argptr);
}
int main()
{
testit(0, 0xFFFFFFFF); // 1st problem: 0xffffffff is not an int
testit(1, NULL); // 2nd problem: NULL is not a char*
}
请注意 testit
预计其第二个参数为 int
或 char*
。 正在传递的参数为 0xffffffff(unsigned int
,不是 int
)和 NULL
(实际是 int
,不是 char*
)。 为本机代码编译程序后,其生成以下输出:
-1
(null)
要求
标头: <stdio.h>
和 <stdarg.h>
已弃用的标头: <varargs.h>
库
C 运行时库的所有版本。
示例
// crt_va.c
// Compile with: cl /W3 /Tc crt_va.c
// The program below illustrates passing a variable
// number of arguments using the following macros:
// va_start va_arg va_copy
// va_end va_list
#include <stdio.h>
#include <stdarg.h>
#include <math.h>
double deviation(int first, ...);
int main( void )
{
/* Call with 3 integers (-1 is used as terminator). */
printf("Deviation is: %f\n", deviation(2, 3, 4, -1 ));
/* Call with 4 integers. */
printf("Deviation is: %f\n", deviation(5, 7, 9, 11, -1));
/* Call with just -1 terminator. */
printf("Deviation is: %f\n", deviation(-1));
}
/* Returns the standard deviation of a variable list of integers. */
double deviation(int first, ...)
{
int count = 0, i = first;
double mean = 0.0, sum = 0.0;
va_list marker;
va_list copy;
va_start(marker, first); /* Initialize variable arguments. */
va_copy(copy, marker); /* Copy list for the second pass */
while (i != -1)
{
sum += i;
count++;
i = va_arg(marker, int);
}
va_end(marker); /* Reset variable argument list. */
mean = sum ? (sum / count) : 0.0;
i = first; /* reset to calculate deviation */
sum = 0.0;
while (i != -1)
{
sum += (i - mean)*(i - mean);
i = va_arg(copy, int);
}
va_end(copy); /* Reset copy of argument list. */
return count ? sqrt(sum / count) : 0.0;
}
Deviation is: 0.816497
Deviation is: 2.236068
Deviation is: 0.000000