una sirve que programacion parametros para macro lenguaje funciones funcion estructura defines define con basica c logging c99 wrapping

sirve - que es un macro en lenguaje c



Cómo envolver printf() en una función o macro? (6)

Hay 2 formas de hacer esto:

  1. Macro de Variadric

    #define my_printf(...) printf(__VA_ARGS__)

  2. función que remite va_args

    #include <stdarg.h> #include <stdio.h> void my_printf(const char *fmt, ...) { va_list args; va_start(args, fmt); vprintf(fmt, args); va_end(args); }

También hay vsnprintf , vfprintf y lo que sea que se te ocurra en stdio .

Esto suena un poco como una pregunta de entrevista, pero en realidad es un problema práctico.

Estoy trabajando con una plataforma integrada y tengo disponibles solo los equivalentes de esas funciones:

  • printf ()
  • snprintf ()

Además, es probable que la implementación de printf () (y la firma) cambie en el futuro cercano, por lo que las llamadas a ella deben residir en un módulo separado, para que sea más fácil migrar más tarde.

Dados esos, ¿puedo envolver las llamadas de registro en alguna función o macro? El objetivo es que mi código fuente llame a THAT_MACRO("Number of bunnies: %d", numBunnies); en miles de lugares, pero las llamadas a las funciones anteriores se ven solo en un lugar.

Compilador: arm-gcc -std = c99


Si puede vivir teniendo que envolver la llamada en dos paréntesis, puede hacerlo así:

#define THAT_MACRO(pargs) printf pargs

Entonces úsalo:

THAT_MACRO(("This is a string: %s/n", "foo")); ^ | OMG

Esto funciona desde el punto de vista del preprocesador, toda la lista de argumentos se convierte en un macro argumento, que se sustituye por el paréntesis.

Esto es mejor que simplemente hacer

#define THAT_MACRO printf

Dado que te permite definirlo:

#define THAT_MACRO(pargs) /* nothing */

Esto "consumirá" los argumentos de la macro, nunca serán parte del código compilado.

ACTUALIZACIÓN Por supuesto que en C99 esta técnica es obsoleta, solo usa una macro variable y sé feliz.


#define TM_PRINTF(f_, ...) printf((f_), ##__VA_ARGS__)

El ## token habilitará el uso de TM_PRINTF("aaa");


#define PRINTF(...) printf(__VA_ARGS__)

Esto funciona así:

Define la macro parametrizada PRINTF para aceptar (hasta) argumentos infinitos, luego la preprocesa desde PRINTF(...) a printf(__VA_ARGS__) . __VA_ARGS__ se usa en definiciones de macro parametrizadas para denotar los argumentos dados (porque no puede nombrar argumentos infinitos, ¿o sí?).


Como puedes usar C99, lo envolveré en una macro variable :

#define TM_PRINTF(f_, ...) printf((f_), __VA_ARGS__) #define TM_SNPRINTF(s_, sz_, f_, ...) snprintf((s_), (sz_), (f_), __VA_ARGS__)

ya que no dijiste que tenías vprintf o algo así. Si tiene algo así, podría envolverlo en una función como Sergey L ha proporcionado en su respuesta.


Biblioteca limitada? ¿Sistema Integrado? ¿Necesita tanto rendimiento como sea posible? ¡No hay problema!

Como se demuestra en esta respuesta a esta pregunta , puede usar el lenguaje ensamblador para ajustar la función que no acepta VA_LIST en las que sí lo hacen, ¡implementando su propio vprintf a bajo costo!

Si bien esto funcionará, y casi con certeza dará como resultado el rendimiento y la abstracción que desea, simplemente le recomendaría que obtenga una biblioteca estándar más completa, tal vez cortando partes de uClibc . Tal solución seguramente será una respuesta más portátil y más útil en general que usar el ensamblaje, a menos que necesites absolutamente cada ciclo.

Es por eso que tales proyectos existen, después de todo.