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_copyva_startva_end 不會傳回值。

備註

va_argva_copyva_endva_start 巨集提供可攜式方法,以在函式接受變動數目的引數時存取函式的引數。 宏有兩個版本:中定義的宏符合 ISO C99 標準;中 STDARG.HVARARGS.H 定義的宏已被取代,但會保留與 ANSI C89 標準之前所撰寫之程式碼的回溯相容性。

這些巨集假設函式接受固定數目的必要引數,後面接著變動數目的選擇性引數。 必要引數會宣告為函式的一般參數,而且可以透過參數名稱進行存取。 選擇性引數是透過 中的 STDARG.H 宏來存取的,或 VARARGS.H 針對 ANSI C89 標準之前撰寫的程式碼,它會設定引數清單中第一個選擇性引數的指標、從清單中擷取引數,並在引數處理完成時重設指標。

在 中 STDARG.H 定義的 C 標準宏,如下所示:

  • va_start 會將 arg_ptr 設為傳遞至函式之引數清單中的第一個選擇性引數。 arg_ptr 引數必須具有 va_list 類型。 引數 prev_param 是必要參數的名稱,緊接在引數清單中的第一個選擇性引數前面。 如果使用暫存器儲存類別宣告 prev_param,則未定義巨集的行為。 第一次使用 va_arg 之前,必須先使用 va_start

  • va_arg 會擷取 arg_ptr 所指定位置中的 type 值,並使用 type 大小決定下一個引數的開始位置,來遞增 arg_ptr 以指向清單中的下一個引數。 在函式中可以使用任意次數的 va_arg,來擷取清單中的引數。

  • va_copy 會以目前的狀態複製引數清單。 src 參數必須已使用 va_start 初始化;它可能已使用 va_arg 呼叫更新,但尚未使用 va_end 重設。 va_argdest 擷取的下一個引數,與擷取自 src 的下一個引數相同。

  • 擷取所有引數之後, va_end 將指標 NULL 重設為 。 傳回函式之前,在使用 va_startva_copy 初始化的每個引數清單上,都必須呼叫 va_end

注意

VARARGS.H 中的巨集已遭取代,並且僅保留與 ANSI C89 標準之前所撰寫程式碼的回溯相容性。 在所有其他情況下,會使用 STDARGS.H 中的巨集。

使用 /clr [Common Language Runtime 編譯] 編譯它們時,使用這些宏的程式可能會因為原生和 Common Language Runtime (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 的第二個參數必須是 intchar*。 正在傳遞的引數是 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

另請參閱

引數存取
vfprintf, _vfprintf_l, vfwprintf, _vfwprintf_l