Historia del tema
Los macros con parámetros son una parte importante del preprocesador de C, aparecieron para facilitar la integración rápida de fragmentos de código repetitivos y simplificar la depuración. Se utilizan para pequeñas funciones, inlining u optimización.
Problema
Los macros no verifican tipos y no realizan una sustitución completa más allá del simple reemplazo textual. Los errores ocurren por la falta de paréntesis y la sustitución de expresiones con efectos secundarios.
Solución
Incluir paréntesis alrededor de los parámetros y definiciones de macros, evitar efectos secundarios en los argumentos y usar funciones inline para casos más complejos.
Ejemplo de código:
#define MAX(a, b) ((a) > (b) ? (a) : (b)) int x = 5, y = 10; int z = MAX(x++, y++); // ¡Llamada peligrosa!
Características clave:
¿Reemplaza siempre el macro el código completamente como una función?
¡No! Un macro es solo una sustitución textual antes de la compilación y puede comportarse de manera diferente a una función si los argumentos son expresiones con efectos secundarios.
¿Se puede usar cualquier llamada (incluyendo ++, --) como parámetro de un macro?
Eso es extremadamente peligroso. Los efectos secundarios ocurrirán varias veces si el parámetro se encuentra en el macro más de una vez.
Ejemplo de código:
// Esta llamada incrementará x o y más de 1 MAX(x++, y++)
¿Cómo incluir correctamente los paréntesis en las definiciones de macros?
Encerrar tanto los parámetros como la expresión dentro del macro en paréntesis para evitar errores de asociatividad al llamar desde otras expresiones.
Durante muchos años, en la empresa se definió el macro #define SQUARE(x) xx, y se utilizó para expresiones como SQUARE(a+1). Surgieron errores inesperados: la expresión se expandía como a+1a+1, lo que difiere de (a+1)*(a+1).
Ventajas:
El macro SQUARE se escribió con paréntesis completos: #define SQUARE(x) ((x)*(x)). Su uso está estandarizado y documentado.
Ventajas: