¿Alternativa estándar a los GCC ##__VA_ARGS__ truco?

 C Programming >> Programación C >  >> Tags >> GCC
¿Alternativa estándar a los GCC ##__VA_ARGS__ truco?


Hay un problema bien conocido con argumentos vacíos para macros variádicas en C99.


ejemplo:


#define FOO(...)       printf(__VA_ARGS__)
#define BAR(fmt, ...) printf(fmt, __VA_ARGS__)
FOO("this works fine");
BAR("this breaks!");

El uso de BAR() lo anterior es incorrecto de acuerdo con el estándar C99, ya que se expandirá a:


printf("this breaks!",);

Tenga en cuenta la coma final:no funciona.


Algunos compiladores (p. ej., Visual Studio 2010) eliminarán silenciosamente esa coma final por usted. Otros compiladores (p. ej., GCC) admiten poner ## delante de __VA_ARGS__ , así:


#define BAR(fmt, ...)  printf(fmt, ##__VA_ARGS__)

Pero, ¿existe una forma compatible con los estándares de obtener este comportamiento?
¿Quizás usando varias macros?


En este momento, el ## La versión parece bastante compatible (al menos en mis plataformas), pero realmente preferiría usar una solución compatible con los estándares.


Preventivo:sé que podría escribir una pequeña función. Estoy tratando de hacer esto usando macros.


Editar :Aquí hay un ejemplo (aunque simple) de por qué querría usar BAR():


#define BAR(fmt, ...)  printf(fmt "\n", ##__VA_ARGS__)
BAR("here is a log message");
BAR("here is a log message with a param: %d", 42);

Esto agrega automáticamente una nueva línea a mis sentencias de registro BAR(), asumiendo fmt es siempre una cadena C entre comillas dobles. NO imprime la nueva línea como un printf() separado, lo que es ventajoso si el registro tiene un búfer de línea y proviene de múltiples fuentes de forma asíncrona.


Respuestas:


Es posible evitar el uso de ,##__VA_ARGS__ de GCC extensión si está dispuesto a aceptar algún límite superior codificado en la cantidad de argumentos que puede pasar a su macro variádica, como se describe en la respuesta de Richard Hansen a esta pregunta. Sin embargo, si no desea tener dicho límite, que yo sepa, no es posible usar solo las funciones de preprocesador especificadas por C99; debes usar alguna extensión al idioma. clang e icc han adoptado esta extensión GCC, pero MSVC no.


En 2001 escribí la extensión GCC para la estandarización (y la extensión relacionada que le permite usar un nombre que no sea __VA_ARGS__ para el resto-parámetro) en el documento N976, pero que no obtuvo respuesta alguna por parte del comité; Ni siquiera sé si alguien lo leyó. En 2016 se volvió a proponer en N2023, y animo a cualquiera que sepa cómo va a hacerlo esa propuesta a que nos lo haga saber en los comentarios.