Compartilhar via


va_arg, va_copy, va_end, va_start

Listas de valores de variável argumento de um.

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 
);  // (Pre-ANSI C89 standardization version)

Parâmetros

  • type
    Tipo de argumento a ser recuperado.

  • arg_ptr
    Ponteiro para a lista de argumentos.

  • dest
    Ponteiro para a lista de argumentos a serem inicializados de src

  • src
    Ponteiro para a lista de argumentos inicializada para copiar a dest.

  • prev_param
    Parâmetro que precede o primeiro argumento opcional.

Valor de retorno

va_arg retorna o argumento atual. va_copy, va_start e va_end não fazem valores de retorno.

Comentários

va_arg, va_copy, va_end, e macros do va_start fornecem uma maneira portátil de acessar os argumentos de uma função quando a função pega um número variável de argumentos. Há duas versões de macros: Macros definidos em STDARG.H segue o padrão ISO C99; macros definidos em VARARGS.H são substituídos mas mantidos para compatibilidade com versões anteriores com código que foi gravado antes do padrão ANSI C89.

Esses macros assumem que a função pega um número fixo de argumentos necessários, seguido de um número variável de argumentos opcionais. Os argumentos necessários são declarados como parâmetros comuns à função e podem ser acessados com os nomes de parâmetro. Os argumentos opcionais são acessados com macros em STDARG.H (ou em VARARGS.H para o código que foi gravado antes do padrão ANSI C89), que define um ponteiro para o primeiro argumento opcional na lista de argumentos, recupera a lista de argumentos, e redefine o ponteiro de argumento quando o processamento for concluído.

Macros C padrão de 2.0, definidos em STDARG.H, são usados como segue:

  • va_start define arg_ptr ao primeiro argumento opcional na lista de argumentos que é passada para a função. O argumento arg_ptr deve ter o tipo de va_list . O argumento prev_param é o nome do parâmetro obrigatório que precede imediatamente o primeiro argumento opcional na lista de argumentos. Se prev_param for declarado com a classe de armazenamento do registro, o comportamento de macro é indefinido. va_start deve ser usado antes que va_arg seja usado pela primeira vez.

  • va_arg recupera um valor de type de local que é determinado por arg_ptr, e incrementa arg_ptr para apontar para o próximo argumento na lista usando o tamanho de type para determinar onde o argumento seguinte começa. va_arg pode ser usado por qualquer número de vezes na função recuperar argumentos da lista.

  • va_copy faz uma cópia de uma lista de argumentos em seu estado atual. O parâmetro de src já deve ser inicializado com va_start; pode ter sido atualizado com chamadas de va_arg , mas não deve ter sido redefinido com va_end. O próximo argumento que é recuperado por va_arg de dest é o mesmo que o próximo argumento que é recuperado de src.

  • Os argumentos foram recuperados, redefinições de va_end o ponteiro para nulo. va_end deve ser chamado a cada lista de argumentos que está inicializada com va_start ou va_copy antes que a função retorna.

Anotação de C++Anotação de C++

Macros em VARARGS.H são substituídas e mantidos apenas para compatibilidade com o código que foi gravado antes do padrão ANSI C89.Em todos os outros casos, use as macros em. STDARGS.H.

Quando são criados usando /clr (compilação do Common Language Runtime), os programas que usam esses macros podem gerar resultados inesperados devido às diferenças entre o native e os sistemas do tipo de Common Language Runtime (CLR). Considere este programa:

#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);
    }
}

int main()
{
    testit(0, 0xFFFFFFFF); // 1st problem: 0xffffffff is not an int
    testit(1, NULL);       // 2nd problem: NULL is not a char*
}

Observe que testit espera o segundo parâmetro ser int ou char*. Os argumentos que estão sendo transmitidos são unsigned int(0xffffffff, não int) e NULL (realmente int, não char*). Quando o programa é compilado para o código nativo, gerencia essas saídas:

  
  

No entanto, quando o programa está sendo criado usando /clr:pure, a causa dos tipos incompatíveis ele gerar uma exceção. A solução é usar conversões explícitas:

int main()
{
   testit( 0, (int)0xFFFFFFFF ); // cast unsigned to int
   testit( 1, (char*)NULL );     // cast int to char*
}

Requisitos

Cabeçalho: <stdio.h e> stdarg.h <>

Cabeçalho preterido: <varargs.h>

Bibliotecas

Todas as versões das Bibliotecas em tempo de execução C.

Exemplo

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

Saída

  

Equivalência do .NET Framework

Classe de System::ParamArrayAttribute

Consulte também

Referência

Acesso a argumento

vfprintf, _vfprintf_l, vfwprintf, _vfwprintf_l