title: Preprocesador de C
text: # Preprocesador de C
  
  El preprocesador de C (cpp) es el preprocesador para el lenguaje de programación C. Es el primer programa invocado por el compilador y procesa directivas como #include, #define e #if. Estas directivas no son específicas de C. En realidad pueden ser usadas con cualquier tipo de archivo.
  El preprocesador utiliza 4 etapas denominadas Fases de traducción. Aunque alguna implementación puede elegir hacer alguna o todas las fases simultáneamente, debe comportarse como si fuesen ejecutadas paso a paso.
  
  # Preprocesador de C
  ## Fases
  
  * Tokenizado léxico - El preprocesador reemplaza la secuencia de trigrafos por los caracteres que representan.
  * Empalmado de líneas - Las líneas de código que continúan con secuencias de escape de nueva línea son unidas para formar líneas lógicas.
  * Tokenización - Reemplaza los comentarios por espacios en blanco. Divide cada uno de los elementos a preprocesar por un carácter de separación.
  * Expansión de macros y gestión de directivas - Ejecuta las líneas con directivas de preprocesado incluyendo las que incluye otros archivos y las de compilación condicional. Además expande las macros. Desde la versión de C de 1999 también gestiona los operadores #Pragma.
  
  # Preprocesador de C
  ## Ejemplos
  
  Esta sección trata con más detalle ejemplos de uso del preprocesador de C. Es crucial que existan buenas prácticas de programación cuando se escriben macros de C. Sobre todo cuando se trabaja en equipo.
  
  # Preprocesador de C
  ## Ejemplos
  ### Incluyendo archivos
  
  La forma más común de usar el preprocesador es incluir otro archivo:
  El preprocesador reemplaza la línea #include <stdio.h> con el archivo de cabecera del sistema con ese nombre. En dicha cabecera se declara, entre otras cosas, la función printf. Más concretamente donde se pone la directiva #include se sustituirá por el contenido completo del archivo 'stdio.h'.
  También puede escribirse usando dobles comillas: #include "stdio.h". Originalmente esta distinción conseguía diferenciar entre los archivos de cabecera del sistema (<>) y los de usuario (""). Los compiladores de C y los entornos de desarrollo actuales disponen de facilidades para indicar dónde se encuentran los distintos archivos de cabecera. Sin embargo se sigue recomendando usar la misma nomenclatura por cuestiones de claridad en el código. La localización de los archivos de cabecera pueden ser indicados desde la línea de comandos o desde un archivo makefile para hacer el código más portable.
  Se puede utilizar cualquier extensión para los archivos de cabecera. Pero, por convención, se utiliza la extensión .h para los archivos de cabecera y .c para los archivos que no son incluidos por ningún otro. También pueden encontrarse otras extensiones. Por ejemplo, los archivos con extensión .def suelen ser archivos cuyo contenido está diseñado para ser incluido muchas veces.
  #include normalmente obliga a usar protectores de #include o la directiva #pragma once para prevenir la doble inclusión, porque si se incluye más de 1 vez el mismo archivo, (dependiendo del contenido) puede causar que se intente declarar varias veces las mismas funciones o tipos de variable, lo que va a generar un error al compilar, esto se intenta prevenir de la siguiente forma:
  Como resultado, al intentar inclurse el archivo por segunda vez, la operación "ifndef" va a dar falso porque __ARCHIVO_H__ ya estaba definido de la primera vez que se incluyó, y a consecuencia se saltea todo el bloque hasta llegar al "endif" que suele estar al final del archivo.
  
  # Preprocesador de C
  ## Ejemplos
  ### Compilación condicional
  
  Las directivas #ifdef, #ifndef, #else, #elif y #endif pueden usarse para realizar compilaciones condicionales.
  La primera línea define una macro __WINDOWS__. Las macros pueden estar definidas por el compilador, se pueden especificar en la línea de comandos al compilador o pueden controlar la compilación del programa desde un archivo makefile.
  El código siguiente comprueba si la macro __WINDOWS__ está definida. Si es así, como en el ejemplo, se incluye el archivo <windows.h>, en caso contrario, se incluye <unistd.h>.
  
  # Preprocesador de C
  ## Ejemplos
  ### Ejemplos de otros usos
  
  Como el preprocesador puede invocarse independientemente del proceso de compilación de código fuente también puede utilizarse como un preprocesador de propósito general para otros tipos de procesamiento de textos. Ver Preprocesadores de propósito general para ver otros ejemplos.
  
  # Preprocesador de C
  ## Definición de macros y expansión
  
  Hay dos tipos de macros: las que son como objetos y las que son como funciones. Las que se asemejan a funciones toman parámetros mientras que las que se asemejan a objetos no. La forma de definir un identificador como una macro de cada tipo es, respectivamente:
  Hay que tener en cuenta que no hay ningún espacio entre el identificador de la macro y el paréntesis izquierdo.
  Cada vez que el identificador aparezca en el código fuente será reemplazado por la lista de tokens. Incluso si está vacía. Los identificadores declarados como funciones solo se reemplazan cuando se invoca con los parámetros con los que se definió la macro.
  Las macros tipo objetos se usan normalmente como parte de prácticas de buena programación para crear nombres simbólicos para constantes. Por ejemplo:
  en vez de utilizar el número tal cual en el código.
  Un ejemplo de macro actuando como función es:
  Esta macro define la forma de convertir radianes a grados. Después podemos escribir RADAGRA(34). El preprocesador sustituirá la llamada a la macro por la multiplicación definida antes. Las macros aquí mostradas están escritas en mayúsculas. Esto permite distinguir fácilmente entre macros y funciones compiladas en el código fuente.
  
  # Preprocesador de C
  ## Definición de macros y expansión
  ### Precedencia
  
  Hay que hacer notar que las macros usan paréntesis alrededor de los argumentos y alrededor de toda la expresión. Si se omite alguno de estos pueden darse efectos no deseados más tarde. Por ejemplo:
  * Sin paréntesis en los argumentos:
     * Macro definida como #define RADAGRA(x) (x * 57.29578)
     * RADAGRA(a + b) se expande como (a + b * 57.29578)
  * Sin paréntesis en la expresión:
     * Macro definida como #define RADAGRA(x) (x) * 57.29578
     * 1 / RADAGRA(a) se expande como 1 / (a) * 57.29578
  probablemente ninguno de los dos se corresponda con el efecto deseado.
  
  # Preprocesador de C
  ## Definición de macros y expansión
  ### Evaluación múltiple de efectos colaterales
  
  Otro ejemplo de macros tipo función es:
  Este ilustra uno de los peligros de usar macros como funciones. Uno de los argumentos (a o b) será evaluado dos veces cuando se llame a la "función". Así que si se evalúa la expresión MIN(++primernumero, segundonumero) el argumento primernumero se incrementará dos veces y no uno como se espera.
  Una forma más segura de lograr el mismo objetivo es usar la construcción typeof.
  Esto logra que los argumentos solo se evalúen una vez. Y, además, que no sea específico del tipo de datos. Esta construcción no es legal en ANSI C. Tanto la palabra clave typeof como el situar sentencias compuestas dentro de los paréntesis son extensiones no estándares implementadas en el compilador GNU C (gcc). Si se usa el compilador gcc se puede resolver el mismo problema usando funciones static inline. Estas son igual de eficientes que sus equivalentes #define. Las funciones inline permiten al compilador comprobar el tipo de los parámetros. En este caso particular puede ser una desventaja porque la función 'max' funciona con distintos tipos de parámetros. Pero, en general, suele ser una ventaja.
  Con ANSI C no hay una solución general para afrontar el efecto colateral de los argumentos en macros.
  
  # Preprocesador de C
  ## Definición de macros y expansión
  ### Concatenación de cadenas
  
  La concatenación de cadenas es una de las características más sutiles, y de la que se puede abusar más fácilmente. Dos argumentos pueden unirse usando el operador ##. Esta característica permite concatenar dos cadenas en el código del preprocesador. Esto se puede usar para construir macros muy elaboradas que actúen casi como las templates de C++. Sin muchos de sus beneficios.
  Por ejemplo:
  La línea MYCASE(widget,23) se expande como case 23: widget_23=23; break. El punto y coma después del paréntesis derecho no se expande pero se convierte en el punto y coma que completa la sentencia break.
  Hay que tener en cuenta que el _ entre ## es 'literal' mientras que los que aparecen en los argumentos _id y _elemento son los nombres de los 'argumentos' de la macro.
  
  # Preprocesador de C
  ## Definición de macros y expansión
  ### Punto y coma
  
  Como se ve en el ejemplo anterior el punto y coma de la última línea de la definición de la macro se omite y la macro parece 'natural' cuando se escribe. Se puede incluir en la definición de la macro pero entonces nos encontraremos con líneas en el código sin punto y coma al final. Esto puede despistar a cualquiera que lea el código. O, aún peor, el usuario puede estar tentado a incluir puntos y coma de todas formas. En la mayoría de las ocasiones puede ser inofensivo (un punto y coma adicional denota una sentencia vacía) pero puede causar errores en los bloques de control de flujo:
  Esto se expande en dos sentencias. La que se pretende printf y una sentencia vacía en cada rama de la construcción if/else. Esto hace que el compilador de un mensaje de error similar a este:
  
  # Preprocesador de C
  ## Definición de macros y expansión
  ### Líneas múltiples
  
  Las macros pueden extenderse tantas líneas como hagan falta. Para ello tan solo habrá que terminar cada línea con una raya a la izquierda (\). La macro terminará en la última línea sin una raya a la izquierda.
  Adecuadamente usadas las macros con varias líneas pueden reducir mucho el tamaño y la complejidad del código fuente de un programa en C. Así se aumenta la legibilidad y mantenibilidad del código.
  
  # Preprocesador de C
  ## Definición de macros y expansión
  ### Entrecomillando los argumentos de las macros
  
  Aunque una cadena pasada a una macro no esté encerrada entre comillas se puede tratar como si lo estuviese usando la directiva "#". Por ejemplo en la macro:
  el código
  se expandirá como
  Esta capacidad puede usarse con la concatenación de cadenas automáticas para depurar macros. Como en el ejemplo siguiente:
  imprimirá el nombre de la expresión y su valor así como el nombre del archivo y la línea donde se ejecuta.
  
  # Preprocesador de C
  ## Definición de macros y expansión
  ### Macros variables
  
  El ANSI C no permite macros que tengan un número variable de argumentos. Pero esta opción fue introducida por varios compiladores y se estandarizó en C99. Las macros variables son particularmente útiles cuando escribimos envolturas para printf. Por ejemplo para mostrar mensajes de advertencia o error.
  
  # Preprocesador de C
  ## Macros X
  
  Un patrón de uso poco conocido del preprocesador de C se conoce como "Macros X". Son la práctica de usar varias veces la directiva #include en el mismo archivo de cabecera. Cada vez en un entorno diferente de definición de macros.
  Cuando se quiera añadir un nuevo comando tan solo habrá que modificar el archivo de cabecera donde hemos definido la Macro X (normalmente con la extensión .def) y definir un nuevo gestor para ese comando. La lista de descripciones, la lista de gestores y la enumeración se actualizarán automáticamente por el preprocesador. Sin embargo en muchos casos esta automatización no es posible.
  
  # Preprocesador de C
  ## Errores y advertencias de compilación definidas por el usuario
  
  La directiva #error inserta un mensaje de error en la salida del compilador.
  Esto muestra "¡ERROR GRAVISIMO!" en la salida del compilador y para la compilación en este punto. Esto es muy útil si no sabes si una línea es compilada o no. También es útil cuando tienes el código muy parametrizado y quieres saber si un #define particular se ha introducido desde el makefile. Como aquí:
  También se pueda usar la directiva #warning para mostrar mensajes en la salida del compilador sin para el proceso. Un uso para esto es mostrar código antiguo que no debería utilizarse pero se hace por razones de compatibilidad.
  Visual Studio.NET no soporta esta directiva y debe usarse la directiva #pragma message.
  Aunque el texto de las directivas #error y #warning no tiene que estar entrecomillado es una buena práctica usarlo. Si no se usan, se pueden encontrar errores con los apostrofes y otros caracteres que puede intentar interpretar el preprocesador.
  
  # Preprocesador de C
  ## Características del procesador específicas del compilador
  
  Las directivas #pragma son directivas específicas del compilador. Cada compilador puede usarlas para lo que crea necesario. Por ejemplo para suprimir un mensaje de error específico.
  
  # Preprocesador de C
  ## Estándar de colocación de macros
  
  Algunos símbolos están predefinidos en ANSI C. Los más usuales son __FILE__ y __LINE__ que se expande como el nombre del archivo y la línea actual respectivamente.
  Esto muestra el valor de x precedido por el archivo y el número de línea. Hay que tener en cuenta que el argumento CADENADONDE se concatena con la cadena que lo sigue.
  
  # Preprocesador de C
  ## Macros específicas del compilador predefinidas
  
  Normalmente hay que revisar la documentación específica del compilador. O ver el proyecto que mantiene una lista con las particularidades de cada compilador. También se puede hacer que el compilador nos diga algunas macros predefinidas útiles:
  * Para el compilador GNU C: gcc -dM -E - < /dev/null
  * Para el compilador ANSI C de HP-UX donde fred.c es un archivo de prueba cualquiera: cc -v fred.c