'stdarg' - listas de argumentos variáveis na linguagem C
Sintaxe:
#include <stdarg.h>
void va_start(va_list ap, last);
type va_arg(va_list ap, type);
void va_end(va_list ap);
void va_copy(va_list dest, va_list src);
Descrição:
Uma função pode ser chamada com um número variável de argumentos sendo estes argumentos de diversos tipos. O arquivo de cabeçalho stdarg.h declara um tipo va_list e define três macros para manipular uma lista de argumentos cuja quantidade e tipos são desconhecidos pela função.
A função deve declarar um objeto do tipo va_list o qual é usado pelas macros va_start, va_arg e va_end.
va_start
A macro va_start inicializa ap para uso posterior por va_arg e va_end e deve ser chamada primeiro.
O parâmetro last é o nome do último parâmetro antes da lista de argumentos variáveis, isto é, o último parâmetro o qual a função conheçe o tipo.
Porque o endereço deste parâmetro pode ser usado na macro va_start, ele não deve ser declarado como uma variável register, ou como uma função ou como um array.
va_arg
A macro va_arg expande para uma expressão que tem o tipo e valor do próximo argumento na chamada. O parâmetro ap é aquele inicializado por va_start. Cada chamada a va_arg modifica ap de modo que a próxima chamada retorna o próximo argumento. O parâmetro type é um nome de tipo. Pode-se apontar para um objeto de um tipo específico simplesmente adicionando um * ao tipo.
O primeiro uso da macro va_arg após a macro va_start retorna o argumento após last. Chamadas sucessivas retornam os valores dos outros argumentos.
Se não existe próximo argumento, ou se type não é compatível com o tipo do próximo argumento, erros aleatórios ocorrerão.
Se ap é passado para uma função que usa va_arg(ap,type) então o valor de ap é destruído após o retorno da função.
va_end
Cada chamada de va_start deve ter uma chamada correspondente a va_end na mesma função. Após a chamada de va_end a variável ap é destruída. Várias chamadas com va_start e va_end aninhadas são possíveis. va_end pode ser uma macro ou uma função.
Exemplo:
A função foo pega uma string de caracteres de formato e exibe o argumento associado com cada caracter de formato baseado no tipo.
#include <stdio.h>
#include <stdarg.h>
void foo(char *fmt, ...) {
va_list ap;
int d;
char c, *p, *s;
va_start(ap, fmt);
while (*fmt)
switch(*fmt++) {
case 's': /* string */
s = va_arg(ap, char *);
printf("string %s\n", s);
break;
case 'd': /* int */
d = va_arg(ap, int);
printf("int %d\n", d);
break;
case 'c': /* char */
/* need a cast here since va_arg only
takes fully promoted types */
c = (char) va_arg(ap, int);
printf("char %c\n", c);
break;
}
va_end(ap);
}
Bibliografia: manpage.