C: varargs com macros no gcc

Palavras-chave: C, gcc, cpp, macros, …, varargs, número de parâmetros variável, variadic macros

Para escrever macros de função com número variável de argumentos:

#define DPRINT(fmt, ...)   printf("DEBUG: "fmt"\\n", ## __VA_ARGS__)

__VA_ARGS__ será substituído pelos parâmetros dados. E o ## entre a vírgula e __VA_ARGS__ se encarregará de remover a vírgula quando o número de argumentos for 0.

Exemplo:

#include <stdio.h>
#define DPRINT(fmt, ...) printf("DEBUG: "fmt"\\n", ##__VA_ARGS__)

int main()
{
  int i= 0, j= 0;
  DPRINT("chegou aqui");
  DPRINT("valor de i = %i, j = %i", i, j);
  return 0;
}

Nota: O Visual C++, a partir da versão 2005, passou a incluir o mesmo recurso.

This entry was posted in C. Bookmark the permalink.

11 Responses to C: varargs com macros no gcc

  1. eljunior says:

    bah, tchê!
    faz um baita tempo que eu queria saber como era isso!
    tanques a lote!

  2. Adenilson Cavalcanti says:

    Amigo

    Pelo que entendi, este mecanismo é dependente de uso de macros que talvez nao existam em outros compiladores.

    A GNU C Library define um conjunto de funcoes que acredito sejam mais portáveis (ANSI C89 e ISO C99) presentes em stdarg.h. Um link para maiores informacoes: http://www.gnu.org/software/libc/manual/html_node/Variadic-Functions.html

    Ou simplesmente “$man stdarg.h” para ver o manual da mesma.

    Atenciosamente

    Adenilson

  3. Adenilson Cavalcanti says:

    Segue um exemplo de uso:

    #include <stdarg.h>
    #include <stdio.h>

    int add_em_up (int count,…)
    {
    va_list ap;
    int i, sum;

    va_start (ap, count); /* Initialize the argument list. */

    sum = 0;
    for (i = 0; i < count; i++)
    sum += va_arg (ap, int); /* Get the next argument value. */

    va_end (ap); /* Clean up. */
    return sum;
    }

    int main (void)
    {
    /* This call prints 16. */
    printf (“%d\n”, add_em_up (3, 5, 5, 6));

    /* This call prints 55. */
    printf (“%d\n”, add_em_up (10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10));

    return 0;
    }

  4. eljunior says:

    que eu saiba __VA_ARGS__ foi apresentado no C99…

  5. Adenilson Cavalcanti says:

    eljunior

    From the fine manual: $man va_start

    CONFORMING TO
    The va_start(), va_arg(), and va_end() macros conform to ANSI
    X3.159-1989 (‘‘C89’’). C99 defines the va_copy() macro.

  6. eljunior says:

    me referi à __VA_ARGS__ (apresentada no post), não à va_copy.

    __VA_ARGS__ também é ISO C99:

    http://www.comeaucomputing.com/techtalk/c99/#variadicmacros

    ou seja: improvável alguma diferença de portabilidade entre os dois modos… ;)

  7. Normalmente o método que você quer é o de varargs (i.e.: para escrever funcões que recebem número variável de parâmetros). Nesse caso a dica era sobre macros, para ser usado em casos específicos e os 2 não são intercambiáveis. Mas é uma boa idéia escrever um outro post sobre varargs propriamente dito :)

  8. Adenilson Cavalcanti says:

    Alfredo

    Acho que valeria a pena um post sobre varargs, é uma técnica muito útil.
    :-)

    eljunior: Sobre o suporte ao C99: http://gcc.gnu.org/gcc-4.1/c99status.html
    (onde pode-se ver que existem itens que faltam ser implementados ou estão simplesmente *quebrados*).

    É sempre uma tática segura usar o padrão ANSI por ser melhor suportado na maioria dos compiladores/plataformas.

    Adenilson

  9. Vivendo e aprendendo. Eu desconhecia a existência da palavra-chave __VA_ARGS__. Sempre usei a seguinte forma:

    #define dprint(fmt, args…) printf(“%s: ” fmt, __func__, ##args)

    Onde ‘args’ pode ser qualquer coisa, ‘argumentos’ se preferir em português :-)

    Agora fiquei curioso, seria isto um gccismo? vou ler a documentação…

  10. Yup, é um gccismo. Trecho da documentação:

    GCC has long supported variadic macros, and used a different syntax that allowed you to give a name to the variable arguments just like any other argument. Here is an example:

    #define debug(format, args…) fprintf (stderr, format, args)

    This is in all ways equivalent to the ISO C example above, but arguably more readable and descriptive.

    Prefiro o gccismo :-)

  11. Muito interessante.
    Embora o comentário do Arnaldo sobre o gccismo seja muito legal também, eu prefiro o que é padrão.

Leave a Reply

Your email address will not be published. Required fields are marked *