Preprocesadores C

Preprocesadores C

Preprocesadores son programas que procesan el código fuente antes de que comience la compilación real. No forman parte del proceso de compilación, pero funcionan por separado, lo que permite a los programadores modificar el código antes de la compilación.

  • Es el primer paso por el que pasa el código fuente C al convertirse en un archivo ejecutable.
  • Los principales tipos de directivas de preprocesador son  Macros Compilación condicional de inclusión de archivos y otras directivas como #undef #pragma, etc.
  • Principalmente estas directivas se utilizan para reemplazar una sección determinada del código C con otro código C. Por ejemplo, si escribimos '#define PI 3.14', el preprocesador reemplaza PI con 3.14.
Preprocesadores C

Tipos de preprocesadores C

Todos los preprocesadores anteriores se pueden clasificar en 4 tipos:

macros

Macros se utilizan para definir constantes o crear funciones que son sustituidas por el preprocesador antes de compilar el código. Los dos preprocesadores #definir y #undef se utilizan para crear y eliminar macros en C.

#definir valor simbólico
#undef simbólico

donde después del preprocesamiento simbólico se ampliará a su valor en el programa.

Ejemplo:

C
   #include         // Macro Definition   #define LIMIT 5   int     main  (){      for     (  int     i     =     0  ;     i      <     LIMIT  ;     i  ++  )     {      printf  (  '%d   n  '       i  );      }      return     0  ;   }   

Producción
0 1 2 3 4  

En el programa anterior, antes de que comience la compilación, la palabra LIMIT se reemplaza por 5. La palabra 'LÍMITE' en la definición de macro se llama plantilla macro y '5' es la macroexpansión.

Nota No hay punto y coma (;) al final de la definición de macro. Las definiciones de macros no necesitan un punto y coma para finalizar.

También hay algunos Macros predefinidas en C los cuales son útiles para proporcionar diversas funcionalidades a nuestro programa.

Una macro definida previamente se puede desdefinir utilizando el preprocesador #undef. Por ejemplo en el código anterior

C
   #include         // Macro Definition   #define LIMIT 5   // Undefine macro   #undef LIMIT   int     main  (){      for     (  int     i     =     0  ;     i      <     LIMIT  ;     i  ++  )     {      printf  (  '%d   n  '       i  );      }      return     0  ;   }   


Producción:

 ./Solution.c: In function 'main': ./Solution.c:13:28: error: 'MAX' undeclared (first use in this function) printf('MAX is: %dn' MAX); ^ ./Solution.c:13:28: note: each undeclared identifier is reported only once for each function it appears in  

Macros con argumentos

También podemos pasar argumentos a macros. Estas macros funcionan de manera similar a las funciones. Por ejemplo

# definir foo(a b) a + b
#definir función(r) r * r

Entendamos esto con un programa:

C
   #include         // macro with parameter   #define AREA(l b) (l * b)   int     main  (){      int     a     =     10       b     =     5  ;          // Finding area using above macro      printf  (  '%d'       AREA  (  a       b  ));      return     0  ;   }   

Producción
Area of rectangle is: 50  

Explicación: En el programa anterior la macro ÁREA(l b) se define para calcular el área de un rectángulo multiplicando su longitud (l) y ancho (b) . Cuando ÁREA(ab) se llama se expande a (a*b) y el resultado se calcula e imprime.

Por favor consulte Tipos de macros en C para más ejemplos y tipos.

Inclusión de archivos

La inclusión de archivos le permite incluir archivos externos (bibliotecas de archivos de encabezado, etc.) en el programa actual. Esto normalmente se hace usando el #incluir directiva que puede incluir tanto archivos del sistema como definidos por el usuario.

Sintaxis

Hay dos formas de incluir archivos de encabezado.

#incluir
#incluir 'Nombre del archivo'

El ' <' y '>' corchetes decirle al compilador que busque el archivo en el directorio estándar mientras comillas dobles ( ' ' ) dígale al compilador que busque el archivo de encabezado en el directorio del archivo fuente.

Ejemplo:

C
   // Includes the standard I/O library   #include            int     main  ()     {      printf  (  'Hello World'  );          return     0  ;   }   

Producción
Hello World 

Compilación condicional

Compilación condicional le permite incluir o excluir partes del código dependiendo de ciertas condiciones. Esto es útil para crear código específico de la plataforma o para depurar. Existen las siguientes directivas de preprocesador condicionales: #if #ifdef #ifndef else #elif y #endif

Sintaxis

La sintaxis general de los preprocesadores condicionales es:

#si
// algún código
#elif
// algo más de código
#demás
// Algo más de código
#endif

La directiva #endif se utiliza para cerrar las directivas de apertura #if #ifdef y #ifndef.

Ejemplo

C
   #include         // Defining a macro for PI   #define PI 3.14159   int     main  (){       // Check if PI is defined using #ifdef   #ifdef PI      printf  (  'PI is defined  n  '  );   // If PI is not defined check if SQUARE is defined   #elif defined(SQUARE)      printf  (  'Square is defined  n  '  );   // If neither PI nor SQUARE is defined trigger an error   #else      #error 'Neither PI nor SQUARE is defined'   #endif   // Check if SQUARE is not defined using #ifndef   #ifndef SQUARE      printf  (  'Square is not defined'  );   // If SQUARE is defined print that it is defined   #else      printf  (  'Square is defined'  );   #endif      return     0  ;   }   

Producción
PI is defined Square is not defined 

Explicación: Este código utiliza directivas de preprocesador condicionales ( #ifdef #elif y #ifndef ) para comprobar si determinadas macros ( PI y CUADRADO ) están definidos. Como PI está definido, el programa imprime ' PI está definido ' luego comprueba si SQUARE no está definido e imprime ' El cuadrado no está definido. '.

Otras directivas

Además de las directivas principales del preprocesador, C también proporciona otras directivas para gestionar el comportamiento y la depuración del compilador.

#pragma:

Proporciona instrucciones específicas al compilador para controlar su comportamiento. Se utiliza para desactivar las advertencias, establecer la alineación, etc.

Sintaxis

#pragma directiva

Algunas de las directivas #pragma se analizan a continuación: 

  1. #inicio pragma: Estas directivas nos ayudan a especificar las funciones que se necesitan ejecutar antes del inicio del programa (antes de que el control pase a main()).
  2. #pragma salida : Estas directivas nos ayudan a especificar las funciones que se necesitan ejecutar justo antes de que salga el programa (justo antes de que el control regrese de main()).

Ejemplo

C
   #include         void     func1  ();   void     func2  ();   // specifying funct1 to execute at start   #pragma startup func1   // specifying funct2 to execute before end   #pragma exit func2   void     func1  ()     {     printf  (  'Inside func1()  n  '  );     }   void     func2  ()     {     printf  (  'Inside func2()  n  '  );     }   int     main  (){      void     func1  ();      void     func2  ();      printf  (  'Inside main()  n  '  );      return     0  ;   }   

Producción
Inside main()  

El código anterior producirá el resultado indicado anteriormente cuando se ejecute en compiladores GCC mientras el resultado esperado era:

Salida esperada

 Inside func1() Inside main() Inside func2()   

Esto sucede porque GCC no admite el inicio o la salida de #pragma. Sin embargo, puede utilizar el siguiente código para obtener el resultado esperado en los compiladores GCC. 

C
   #include         void     func1  ();   void     func2  ();   void     __attribute__  ((  constructor  ))     func1  ();   void     __attribute__  ((  destructor  ))     func2  ();   void     func1  ()   {      printf  (  'Inside func1()  n  '  );   }   void     func2  ()   {      printf  (  'Inside func2()  n  '  );   }   int     main  ()   {      printf  (  'Inside main()  n  '  );      return     0  ;   }   

Producción
Inside func1() Inside main() Inside func2()  

En el programa anterior hemos utilizado algunos sintaxis específicas de modo que una de las funciones se ejecute antes de la función principal y la otra se ejecute después de la función principal.

Crear cuestionario