Una macro es un nombre que el preprocesador reemplaza por algo de texto antes de que el compilador se ejecute. Ese es todo el mecanismo, y cada regla de esta página es consecuencia de él: las macros no tienen tipos, no respetan el ámbito, no evalúan argumentos y no saben qué es una llamada a función. Copian texto.
Usadas con cuidado son indispensables: interruptores de portabilidad, macros de aserción que capturan el número de línea, constantes de tiempo de compilación que sirven como tamaños de array. Usadas sin cuidado producen errores que parecen imposibles hasta que expandes el archivo.
Macros tipo objeto
La forma más simple define un nombre que representa un valor:
Por convención estos nombres van en MAYUSCULAS_CON_GUION_BAJO para que quien lee distinga de un vistazo que un símbolo es una macro y no una variable. Aquí esa convención importa más que de costumbre, porque las macros ignoran el ámbito: un #define dentro de una función sigue aplicándose al resto del archivo, y reescribirá sin problema una variable con el mismo nombre en otra función.
#undef NOMBRE elimina una definición, así que un nombre puede redefinirse después sin un aviso de redefinición.
Macros tipo función
Pon una lista de parámetros justo después del nombre —sin espacio antes del paréntesis de apertura— y la macro toma argumentos:
La regla del espacio es real: #define SQUARE (x) ((x)*(x)) define una macro tipo objeto llamada SQUARE cuyo texto de reemplazo empieza con (x). El error de compilación que venga después no mencionará los espacios.
Las reglas de los paréntesis
Son dos, y ambas existen porque el cuerpo se pega dentro de una expresión que no puedes ver mientras escribes la macro.
Regla 1: pon entre paréntesis cada parámetro. Sin eso, un argumento que es a su vez una expresión queda desgarrado por la precedencia:
#define SQUARE_BAD(x) x * x
SQUARE_BAD(2 + 3) /* se convierte en 2 + 3 * 2 + 3 == 11, no 25 */
Regla 2: pon entre paréntesis el cuerpo entero. Sin eso, la expresión que rodea desgarra el resultado:
#define DOUBLE_BAD(x) (x) + (x)
10 / DOUBLE_BAD(5) /* se convierte en 10 / (5) + (5) == 7, no 1 */
Ejecuta ambos fallos junto a sus versiones arregladas:
Ambas versiones malas compilan sin un solo aviso y producen números equivocados. El hábito que hay que construir es mecánico: envuelve cada parámetro y luego envuelve el resultado. ((a) > (b) ? (a) : (b)) se ve ruidoso, y el ruido es justamente el punto.
La trampa de la evaluación múltiple
Los paréntesis no te salvan del segundo peligro. Una macro pega el texto de su argumento en cada lugar donde aparece el parámetro, así que un argumento con efecto secundario ocurre más de una vez:
La macro se expande a ((i++) > (j) ? (i++) : (j)). La comparación incrementa i a 6 y compara 5 con 3; la rama verdadera vuelve a incrementar i a 7 y produce 6. Así que m es 6 e i es 7, y ninguno de los dos es lo que "el mayor de i y j" debería dar. Una función max(i++, j) sería correcta, porque el argumento se evalúa una vez antes de la llamada.
La misma trampa atrapa a cualquier cosa con efecto secundario: SQUARE(rand()) llama a rand() dos veces y multiplica dos números distintos. CHECK(read_byte()) consume dos bytes.
Dos defensas, en orden de preferencia:
- Usa una función de verdad. Si la necesitas para varios tipos, escribe una por tipo, o usa una función
static inlineen una cabecera. - Si tiene que ser una macro, documenta bien alto que los argumentos se evalúan más de una vez, y mantén los puntos de llamada libres de efectos secundarios.
Macros de varias líneas y do-while(0)
El cuerpo de una macro puede abarcar varias líneas si cada línea menos la última termina en una barra invertida. La versión ingenua se ve bien:
#define LOG_TWICE(msg) \
printf("%s\n", msg); \
printf("%s\n", msg)
Y luego se rompe, en silencio, en el único lugar donde importa:
if (verbose)
LOG_TWICE("hola");
else
printf("silencio\n");
Después de la sustitución el if se queda solo con el primer printf, el segundo se ejecuta sin condición y el else ya no tiene un if que le corresponda: un error de compilación cuyo mensaje no apunta a ningún lugar útil. Envolver el cuerpo en llaves a secas no mejora nada: el ; final tras LOG_TWICE("hola") se convierte en una sentencia vacía que termina el if, y el else vuelve a romperse.
El modismo que funciona es do { ... } while (0):
do { ... } while (0) es una sola sentencia, ejecuta su cuerpo exactamente una vez y exige un punto y coma después, así que el punto de llamada se lee como una llamada a función corriente y se comporta como tal en cualquier contexto de control de flujo. Ojo con las barras invertidas: un espacio suelto después de una barra termina la continuación y produce un error desconcertante.
Macros predefinidas y patrones de aserción
El preprocesador define varias macros por su cuenta, y son la razón por la que algunas cosas sencillamente no pueden ser funciones:
__FILE__ y __LINE__ se expanden donde están escritos, así que ponerlos dentro de una macro captura la posición de quien llama. Una función no podría hacer esto: dentro de una función siempre reportarían el archivo y la línea de la propia función de registro. Así es exactamente como la macro estándar assert reporta la ubicación de la expresión que falló.
Otros nombres predefinidos útiles: __DATE__, __TIME__ y __STDC_VERSION__ (por ejemplo 201710L para C17).
Dos operadores que vale la pena conocer
Dentro del cuerpo de una macro, # convierte un parámetro en un literal de cadena ("stringizing") y ## pega tokens ("token pasting").
SHOW(width * height) se convierte en printf("width * height" " = %d\n", (width * height));: el compilador une los literales de cadena adyacentes, así que una sola llamada imprime tanto el texto de la expresión como su valor. Es un truco de depuración que vale la pena recordar.
## es más raro y aparece sobre todo en macros de generación de código: #define MAKE_VAR(n) int var_##n convierte MAKE_VAR(3) en int var_3. Úsalo con moderación; los identificadores construidos por el preprocesador no se pueden buscar por nombre, lo que hace que el código sea difícil de recorrer.
Macros frente a funciones frente a const
Usa la herramienta más débil que resuelva el trabajo:
- Variable
const:const double PI = 3.14159;tiene tipo, obedece el ámbito, aparece en el depurador y no puede ser redefinida por una cabecera ajena. Prefiérela para valores usados en tiempo de ejecución. enum:enum { MAX_USERS = 100 };da una constante entera con nombre que sirve donde C exige una constante de tiempo de compilación, con tipo y con ámbito. Buena para límites enteros.- Función
static inline: con comprobación de tipos, evalúa cada argumento exactamente una vez, y los compiladores modernos la integran igual que haría una macro. Este es el reemplazo correcto para casi cualquier macro tipo función. - Macro: cuando necesitas
__LINE__, cuando la cosa debe funcionar antes de que existan los tipos (tamaños de array en código antiguo), cuando estás cambiando código con compilación condicional o cuando estás generando código repetitivo.
Un lugar donde las macros siguen sin rival es el tamaño de los arrays, porque el resultado debe ser una constante de tiempo de compilación:
Esta tiene su propia salvedad bien conocida: solo es correcta para un array genuino. Pásale un puntero —que es en lo que se convierte un array cuando se entrega a una función— y sizeof mide el puntero, dando una respuesta equivocada y silenciosamente segura de sí misma.
Depurar una macro
Cuando una macro se porta mal, no te quedes mirándola. Expándela:
gcc -E program.c | tail -30
El texto sustituido te dice de inmediato si el problema es un paréntesis que falta, una doble evaluación o un nombre que choca con otra cosa. Compila también con -Wall -Wextra: GCC y clang agregan notas de "in expansion of macro" que conectan la línea del error reportado con la definición.
A continuación: archivos de cabecera, donde #define e #include se combinan para que un proyecto abarque muchos archivos fuente sin pegar dos veces las mismas declaraciones.
Preguntas frecuentes
¿Qué es una macro en C?
Un fragmento de texto con nombre que el preprocesador sustituye en tu código fuente antes de la compilación. #define MAX 100 hace que cada MAX posterior se convierta en 100; #define SQUARE(x) ((x) * (x)) toma argumentos y los sustituye dentro de un patrón. Las macros no tienen tipos y no obedecen reglas de ámbito: son sustitución de texto.
¿Por qué las macros de C necesitan tantos paréntesis?
Porque el cuerpo se pega dentro del código que la rodea y luego se analiza en conjunto. #define SQUARE(x) x * x convierte SQUARE(2 + 3) en 2 + 3 * 2 + 3, que da 11 en vez de 25. Envolver cada argumento y el cuerpo entero —((x) * (x))— hace que el texto sustituido se agrupe como querías, sin importar qué haya alrededor.
¿Cuál es la diferencia entre una macro y una función en C?
Una función se compila una vez, tiene comprobación de tipos y evalúa cada argumento exactamente una vez. Una macro se pega en cada uso, no comprueba nada y puede evaluar un argumento varias veces, así que MAX(i++, j) puede incrementar i dos veces. Prefiere funciones (y const/enum para constantes); usa macros para lo que las funciones no pueden hacer, como capturar __LINE__ o generar código.
¿Por qué una macro de varias líneas se envuelve en do { ... } while (0)?
Para que se comporte como una sola sentencia. Un cuerpo con llaves a secas se rompe cuando lo sigue un punto y coma dentro de un if/else (el punto y coma termina el if antes de tiempo), y una simple secuencia de sentencias se rompe en un if sin llaves. do { ... } while (0) es una sola sentencia que acepta un punto y coma final y ejecuta su cuerpo exactamente una vez.