O comando '
man stdarg' lhe dará todas as informações necessárias. Esta página é apenas um resumo do que você encontrará nesse manual. Na seção de referências há um link para o manual online.
#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);
va_list
Tipo de dados usado para manipular a lista de argumentos. A variável definida com este tipo provavelmente é um ponteiro, mas isso é irrelevante para nós (abstração!). Mas é necessário saber que antes de utilizar essa variável precisamos inicializá-la usando...
va_start
Ela toma dois argumentos, uma variável do tipo va_list e o nome da última variável conhecida na lista de parâmetros. Como os argumentos podem ser passados na pilha ou em registradores, essa função torna-se necessária para posicionar o ponteiro corretamente no Stack Frame da função ou para alocar memória e copiar os valores dos registradores utilizados. Depois de inicializada, podemos acessar os argumentos através da macro...
va_arg
Que retornará o próximo argumento da lista apontada pela variável de tipo va_list. Também toma dois argumentos, a variável va_list e o tipo de dados do argumento. Já que são argumentos variáveis, podem também ser de tipos variáveis, e nós é que informamos os tipos corretamente. Quando terminamos de manipular os argumentos, chamamos a macro...
va_end
Necessária para liberar memória (caso tenha sido alocada) e em alguma implementações fechar o bloco. Em algumas versões da biblioteca, va_start abre um bloco com {, e não terminar a função com va_end resultará em erro de compilação. Essa macro toma apenas um argumento de tipo va_list.
va_copy
Existem algumas funções que tomam como argumentos uma lista de parâmetros variáveis (va_list). Como por exemplo vprintf() e vscanf(). Sendo va_list um ponteiro, essas funções irão modificar o local para onde ele aponta. Se você não precisar mais do ponteiro após chamar tais funções, não precisará de uma cópia. Entretanto, se for usar a lista novamente, você vai precisar. Na maior parte das implementações, va_list é apenas um ponteiro para um local no Stack Frame da função, e é seguro fazer:
va_list ap;
va_start(ap, last);
va_list aq = ap;
Entretanto, algumas implementações declaram 'ap' como um vetor de ponteiros, e aí seria necessário fazer:
*aq = *ap;
Como não queremos nos preocupar com isso, podemos simplesmente utilizar va_copy.
A biblioteca stdarg.h não permite que uma função não tenha argumentos fixos. Portanto, ao menos um parâmetro é necessário. Entretanto, há a biblioteca mais antiga varargs.h que permite isso. O manual de stdarg(3) dá um exemplo sobre como utilizá-la.