HOW-TO: Macros en C (III) – «Parámetros»

Publicado por Alejandro Escario en

Como último artículo de la serie, vamos a adentrarnos un poco más en la declaración de elementos similares a las funciones con macros , para ser más exactos, con sus argumentos y posibilidades:

Convertir a String

En ocasiones no es de un gran interés tratar de la misma manera todos los argumentos que le pasamos a este tipo de funciones de preprocesador.

En el caso concreto de que deseemos tratar el argumento como un String constante, habremos de precederlo con el símbolo ‘#‘, demnaera que estamos convirtiendo en constantes dichos parámetros, pero veamos un ejemplo que he sacado de gnu.org, ya que me parece bastante ilustrativo.

#define WARN_IF(EXP) 
     do { if (EXP) 
             fprintf (stderr, "Warning: " #EXP "n"); } 
     while (0)
     WARN_IF (x == 0);

Este pedazo de código nos dará una salida como la siguiente:

do { if (x == 0) fprintf (stderr, «Warning: » «x == 0» «n»); } while (0);

Es decir, el argumento EXP se sustituye como argumento en el primer caso y como un string en el segundo.

Una de las grandes ventajas de la conversión a String de este tipo de macros, es que no sólo añade dobles comillas, sino que escapa los caracteres necesarios para que la cadena se muestre tal y como es, a no ser que esta se encuentre dentro de una cadena de texto ya o sea un carácter como ‘n‘.

Finalmente puede resultarnos de utilidad concatenar un par de tokens dados dentro de una macro; para ello podremos hacer uso de ‘##

Parámetros indefinidos

Algo que puede resultarnos muy interesante e incluso increíble cuando empezamos a utilizar C, es que, si bien nos han enseñado a que las funciones tienen un número definido de parámetros, ¿cómo es posible la existencia de funciones como printf?

Al igual que para las funciones, existe una forma de hacer que una macro acepte un número no definido de parámetros, y este método aparece en forma de __VA_ARGS__. Este token nos permitirá sustotuir en nuestro macro los ‘‘ por los valores que se le han pasado a la función.

#define log(...) printf(__VA_ARGS__)

Si queremos ser más descriptivos con los parámetros podemos sustituir ‘‘ por ‘<nombre>…‘, por ejemplo:

#define log(args...) printf(args)

Si queremos especificar un número mínimo de argumentos, podemos hacerlo de la siguiente manera:

#define log(formato, args...) printf(formato, args)

pero esto hace que sea obligatorio, en todo momento, si no pasar un segundo argumento, sí escribir la coma después del primero. Para solucionar este problema, de nuevo acudimos al manual de gnu.org que nos dice que echemos mano de ‘##‘, de manera que podamos omitir, si lo deseamos el segundo parámetro y la coma de después del primero al llamar a la macro:

#define log(formato, args...) printf(formato, ##args)
Categorías: C/C++Manuales