va_arg, va_copy, va_end, va_start

Greift auf Variablenargumentelisten zu.

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)

Parameter

type
Typ des abzurufenden Arguments.

arg_ptr
Zeiger auf die Liste der Argumente.

dest
Zeiger auf die Liste von Argumenten, die von src initialisiert werden

src
Zeiger auf die initialisierte Liste von Argumenten, die von dest kopiert werden.

prev_param
Parameter, der dem ersten optionalen Argument vorausgeht.

Rückgabewert

va_arg gibt das aktuelle Argument zurück. va_copyva_start und va_end geben keine Werte zurück.

Hinweise

Die Makros va_arg, va_copy, va_end und va_start ermöglichen auf portierbare Weise, auf die Argumente für eine Funktion zuzugreifen, wenn die Funktion eine variable Anzahl von Argumenten akzeptiert. Es gibt zwei Versionen der Makros: Die makros, die gemäß STDARG.H dem ISO C99-Standard definiert sind. Die definierten VARARGS.H Makros sind veraltet, werden jedoch aus Gründen der Abwärtskompatibilität mit Code beibehalten, der vor dem ANSI C89-Standard geschrieben wurde.

Diese Makros setzen voraus, dass die Funktion eine feste Anzahl von erforderlichen Argumenten akzeptiert, gefolgt von einer variablen Anzahl von optionalen Argumenten. Die erforderlichen Argumente werden als gewöhnliche Parameter für die Funktion deklariert und können über die Parameternamen aufgerufen werden. Auf die optionalen Argumente wird über die Makros in STDARG.H (oder VARARGS.H für Code zugegriffen, der vor dem ANSI C89-Standard geschrieben wurde), der einen Zeiger auf das erste optionale Argument in der Argumentliste festlegt, Argumente aus der Liste abruft und den Zeiger zurücksetzt, wenn die Argumentverarbeitung abgeschlossen ist.

Die in STDARG.HC definierten Standardmakros werden wie folgt verwendet:

  • va_start legt arg_ptr auf das erste optionale Argument in der Liste der Argumente fest, die an die Funktion übergeben wird. Das Argument arg_ptr muss über den Typ va_list verfügen. Das Argument prev_param ist der Name des erforderlichen Parameters, der dem ersten optionalen Argument in der Argumentliste direkt vorausgeht. Wenn prev_param mit der Registerspeicherklasse deklariert wird, ist das Verhalten des Makros undefiniert. va_start muss verwendet werden, bevor va_arg zum ersten Mal verwendet wird.

  • va_arg ruft einen type-Wert vom Speicherort ab, der von arg_ptr angegeben wird, und inkrementiert arg_ptr, um auf das folgende Argument in der Liste zu verweisen, indem mithilfe der Größe von type bestimmt wird, wo das folgende Argument beginnt. va_arg kann in der Funktion beliebig oft verwendet werden, um Argumente aus der Liste abzurufen.

  • va_copy erstellt eine Kopie von einer Argumentliste im aktuellen Zustand. Der src-Parameter muss bereits mit va_start initialisiert sein. Er kann mithilfe von va_arg-Aufrufen aktualisiert worden sein, doch darf er nicht mit va_end zurückgesetzt worden sein. Das folgende Argument, das von va_arg aus dest abgerufen wird, entspricht dem folgenden Argument, das von src abgerufen wird.

  • Nachdem alle Argumente abgerufen wurden, va_end setzt der Zeiger auf NULL. va_end muss in jeder mit va_start oder va_copy initialisierten Argumentliste aufgerufen werden, bevor die Funktion Daten zurückgibt.

Hinweis

Die in VARARGS.H definierten Makros sind als veraltet markiert und werden nur beibehalten, weil sie für Code abwärts kompatibel sind, der vor dem ANSI-Standard C89 geschrieben wurde. Verwenden Sie in allen anderen Fällen die Makros in STDARGS.H.

Wenn sie mithilfe /clr der Kompilierung (Common Language Runtime Compilation) kompiliert werden, generieren Programme, die diese Makros verwenden, möglicherweise unerwartete Ergebnisse aufgrund von Unterschieden zwischen systemeigenen und common language runtime (CLR)-Typsystemen. Beachten Sie dieses Programm:

#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*
}

Berücksichtigen Sie, dass testit als zweiten Parameter entweder int oder char* voraussetzt. Die übergebenen Argumente sind 0xffffffff ( unsigned int, aber nicht int) und NULL (tatsächlich ein int, aber kein char*). Wenn das Programm für nativen Code kompiliert wird, erzeugt es diese Ausgabe:

-1

(null)

Anforderungen

Kopfzeile:<stdio.h> und <stdarg.h>

Veraltete Kopfzeile:<varargs.h>

Bibliotheken

Alle Versionen der C-Laufzeitbibliotheken.

Beispiel

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

Siehe auch

Argumentzugriff
vfprintf, _vfprintf_l, vfwprintf, _vfwprintf_l