www.samueldiasneto.com: 'stdarg' na linguagem C

'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.