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.
bah, tchê!
faz um baita tempo que eu queria saber como era isso!
tanques a lote!
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
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;
}
que eu saiba __VA_ARGS__ foi apresentado no C99…
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.
…
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… ;)
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 :)
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
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…
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 :-)
Muito interessante.
Embora o comentário do Arnaldo sobre o gccismo seja muito legal também, eu prefiro o que é padrão.