va_arg、va_copy、va_end、va_startva_arg, va_copy, va_end, va_start

访问变量参数列表。Accesses variable-argument lists.

语法Syntax

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)

参数Parameters

typetype
要检索的参数类型。Type of argument to be retrieved.

arg_ptrarg_ptr
指向参数列表的指针。Pointer to the list of arguments.

destdest
指向要从src初始化的自变量列表的指针Pointer to the list of arguments to be initialized from src

srcsrc
一个指针,指向要复制到目标的参数的已初始化列表。Pointer to the initialized list of arguments to copy to dest.

prev_paramprev_param
位于第一个可选实参之前的形参。Parameter that precedes the first optional argument.

返回值Return Value

va_arg返回当前参数。va_arg returns the current argument. va_copyva_startva_end不返回值。va_copy, va_start and va_end do not return values.

备注Remarks

当函数采用可变数量的参数时, va_argva_copyva_endva_start宏提供一种可移植的方式来访问函数的参数。The va_arg, va_copy, va_end, and va_start macros provide a portable way to access the arguments to a function when the function takes a variable number of arguments. 有两个版本的宏:在 STDARG.H 中定义的宏。H 符合 ISO C99 标准;以 VARARGS 定义的宏。H 已弃用,但会保留,以便与在 ANSI C89 标准之前编写的代码保持向后兼容。There are two versions of the macros: The macros defined in STDARG.H conform to the ISO C99 standard; the macros defined in VARARGS.H are deprecated but are retained for backward compatibility with code that was written before the ANSI C89 standard.

这些宏假定函数采用固定数量的必需参数,后面是可变数量的可选参数。These macros assume that the function takes a fixed number of required arguments, followed by a variable number of optional arguments. 将必需参数声明为函数的普通参数,且可通过参数名称访问它们。The required arguments are declared as ordinary parameters to the function and can be accessed through the parameter names. 可选参数可通过 STDARG.H 中的宏访问(对于在 ANSI C89 标准之前编写的代码,通过 VARARGS.H),其将指针设置为参数列表中的第一个可选参数、检索列表中的参数并在参数处理完成后重置指针。The optional arguments are accessed through the macros in STDARG.H (or VARARGS.H for code that was written before the ANSI C89 standard), which sets a pointer to the first optional argument in the argument list, retrieves arguments from the list, and resets the pointer when argument processing is completed.

STDARG.H 中定义的 C 标准宏使用方法如下:The C standard macros, defined in STDARG.H, are used as follows:

  • va_startarg_ptr设置为传递给函数的参数列表中的第一个可选参数。va_start sets arg_ptr to the first optional argument in the list of arguments that's passed to the function. 参数arg_ptr必须具有va_list类型。The argument arg_ptr must have the va_list type. 参数prev_param是紧跟参数列表中第一个可选参数之前的必需参数的名称。The argument prev_param is the name of the required parameter that immediately precedes the first optional argument in the argument list. 如果prev_param是用 register 存储类声明的,则宏的行为是不确定的。If prev_param is declared with the register storage class, the macro's behavior is undefined. 首次使用va_arg之前,必须使用va_startva_start must be used before va_arg is used for the first time.

  • va_argarg_ptr提供的位置检索类型的值,并通过使用类型的大小来确定下一个参数的开始位置,从而递增arg_ptr ,以指向列表中的下一个参数。va_arg retrieves a value of type from the location that's given by arg_ptr, and increments arg_ptr to point to the next argument in the list by using the size of type to determine where the next argument starts. 在函数中,可以使用va_arg来检索列表中的参数。va_arg can be used any number of times in the function to retrieve arguments from the list.

  • va_copy创建其当前状态的自变量列表的副本。va_copy makes a copy of a list of arguments in its current state. Src参数必须已通过va_start初始化;它可能已使用va_arg调用进行了更新,但不得使用va_end重置。The src parameter must already be initialized with va_start; it may have been updated with va_arg calls, but must not have been reset with va_end. Va_argdest检索到的下一个参数与从src检索到的下一个参数相同。The next argument that's retrieved by va_arg from dest is the same as the next argument that's retrieved from src.

  • 检索所有参数后, va_end会将指针重置为NULLAfter all arguments have been retrieved, va_end resets the pointer to NULL. 在函数返回之前,必须在用va_startva_copy初始化的每个参数列表上调用va_endva_end must be called on each argument list that's initialized with va_start or va_copy before the function returns.

备注

VARARGS.H 中的宏已弃用,将其保留只为保证与写于 ANSI C89 标准之前的代码的后向兼容性。The macros in VARARGS.H are deprecated and are retained only for backwards compatibility with code that was written before the ANSI C89 standard. 在所有其他情况下,请使用 STDARGS.H 中的宏。In all other cases, use the macros in STDARGS.H.

它们使用 /clr(公共语言运行时编译)编译时,使用这些宏的程序可能会因为本机和公共语言运行时 (CLR) 类型系统之间的差异而生成意外的结果。When they are compiled by using /clr (Common Language Runtime Compilation), programs that use these macros may generate unexpected results because of differences between native and common language runtime (CLR) type systems. 考虑此程序:Consider this program:

#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希望它的第二个参数是intchar*Notice that testit expects its second parameter to be either an int or a char*. 传递的参数为0xffffffff (无符号 整数,而不是int)和NULL (实际上是int,而不是字符*)。The arguments being passed are 0xffffffff (an unsigned int, not an int) and NULL (actually an int, not a char*). 为本机代码编译程序后,其生成以下输出:When the program is compiled for native code, it produces this output:

-1

(null)

要求Requirements

标头: <stdio.h> 和 <stdarg.h>Header: <stdio.h> and <stdarg.h>

弃用的标头: <varargs.h>Deprecated Header: <varargs.h>

Libraries

C 运行时库的所有版本。All versions of the C run-time libraries.

示例Example

// 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

请参阅See also

参数访问Argument Access
vfprintf、_vfprintf_l、vfwprintf、_vfwprintf_lvfprintf, _vfprintf_l, vfwprintf, _vfwprintf_l