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 srcsrc
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++ |
---|
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