Las macros X son un uso idiomático de las macros del lenguaje de programación para generar estructuras de datos o código similares a listas. Son más útiles cuando al menos algunas de las listas no se pueden componer mediante indexación, como en tiempo de compilación . Proporcionan un mantenimiento confiable de listas paralelas cuyos elementos correspondientes se deben declarar o ejecutar en el mismo orden.
Ejemplos de tales listas incluyen en particular la inicialización de matrices, en conjunto con declaraciones de constantes de enumeración y prototipos de funciones; la generación de secuencias de declaraciones y brazos de conmutación; etc.
El uso de macros X se remonta a la década de 1960. [1] Sigue siendo útil en los lenguajes de programación C y C++ actuales , pero sigue siendo relativamente desconocido. [2] [3]
Una aplicación macro X consta de dos partes:
La lista se define mediante una macro o archivo de encabezado (denominado LIST
) que no genera código por sí mismo, sino que simplemente consiste en una secuencia de invocaciones de una macro (denominada clásicamente " X
") con los datos de los elementos. Cada expansión de LIST
está precedida por una definición de X
con la sintaxis para un elemento de lista. La invocación de LIST
se expande X
para cada elemento de la lista.
Este ejemplo define una lista de variables y genera automáticamente sus declaraciones y una función para imprimirlas.
Primero, la definición de la lista. Las entradas de la lista pueden contener múltiples argumentos, pero aquí solo se utiliza el nombre de la variable.
#define LISTA_DE_VARIABLES \ X(valor1) \ X(valor2) \ X(valor3)
Luego ampliamos esta lista para generar las declaraciones de variables:
#define X(nombre) int nombre; LISTA_DE_VARIABLES #undef X
De manera similar, podemos generar una función que imprima las variables y sus valores:
void print_variables ( void ) { #define X(nombre) printf("%s = %d\n", #nombre, nombre); LISTA_DE_VARIABLES #undef X }
Cuando se ejecuta a través del preprocesador C , se genera el siguiente código. Se han agregado saltos de línea y sangría para facilitar la lectura, aunque en realidad no los genera el preprocesador:
int valor1 ; int valor2 ; int valor3 ; void print_variables ( void ) { printf ( "%s = %d \n " , "valor1" , valor1 ); printf ( "%s = %d \n " , "valor2" , valor2 ); printf ( "%s = %d \n " , "valor3" , valor3 ); }
Este ejemplo tiene como objetivo mejorar la legibilidad del uso de la macro X mediante:
#define PARA_LISTA_DE_VARIABLES(DO) \ DO(id1, nombre1) \ DO(id2, nombre2) \ DO(id3, nombre3) \
Como se indicó anteriormente, ejecute esta lista para generar las declaraciones de variables:
#define DEFINE_NOMBRE_VAR(id, nombre, ...) int nombre; PARA_LISTA_DE_VARIABLES ( DEFINE_NOMBRE_VAR )
o declarar una enumeración:
#define DEFINE_ENUMERATION(id, nombre, ...) nombre = id, enumeración mi_id_tipo_lista { PARA_LISTA_DE_VARIABLES ( DEFINE_ENUMERATION ) }
De manera similar, podemos generar una función que imprima las variables y sus nombres:
void print_variables ( void ) { #define IMPRIMIR_NOMBRE_Y_VALOR(id, nombre, ...) printf("%s = %d\n", #nombre, nombre); PARA_LISTA_DE_VARIABLES ( IMPRIMIR_NOMBRE_Y_VALOR ) }