martes, 25 de febrero de 2014

Pre-procesador en Lenguaje C


El preprocesador es una parte del compilador que se ejecuta en primer lugar, cuando se compila un fuente C, y que realiza unas determinadas operaciones, independientes del propio lenguaje C. Estas operaciones se realizan a nivel léxico y consisten en:
  • la inclusión de otros textos en un punto del archivo fuente,
  • la realización de sustituciones, y
  • la eliminación de ciertas partes del código fuente.
Debemos tener en cuenta que el preprocesador trabaja únicamente con el texto del fuente y no tiene en cuenta ningún aspecto sintáctico ni semántico del lenguaje.

Directivas de preprocesado

El control del preprocesador se realiza mediante determinadas directivas incluidas en el fuente. Una directiva es una palabra que interpreta el preprocesador, y siempre va precedida por el símbolo # situado al principio de línea.

La directiva #define se utiliza para definir una macro. Las macros proporcionan principalmente un mecanismo para la sustitución léxica. Una macro se define de la forma

#define identificador secuencia

Cada ocurrencia de identificador en el código fuente es sustituida por secuencia.

#include <stdio.h>

#define TECLA  'A'
#define MENSAJE1 "Se ha pulsado la tecla 'A'\n"
#define MENSAJE2 "No se ha pulsado la letra 'A'\n"


main()
{
 if( getchar() == TECLA )
  printf(MENSAJE1);

 else
  printf(MENSAJE2);
}

Puede definirse una macro sin una secuencia de caracteres, y una macro se puede indefinir mediante la directiva #undef.

El estado de una macro, si está definida o no, se puede comprobar mediante las directivas #ifdef y#ifndef. Estas dos directivas se deben completar con una #endif y, el texto comprendido entre ambas es procesado si la macro está definida. Todas las directivas deben ser completadas en el mismo fuente y pueden ser anidadas.

#ifndef PI /* Comprueba si está definida la macro p */

 #define PI 3.1415927 /* Si no está definida, lo hace */

#endif

El preprocesador nos permite también incluir también otros ficheros en un fuente C. Esto se consigue con la directiva #include. Esta puede tomar tres formas:

#include <fichero>
#include "fichero"
#include macro

La diferencia entre la primera y la segunda está en el lugar dónde se buscará el fichero en cuestión. Normalmente se utiliza la primera para ficheros proporcionados por la biblioteca del compilador, y la segunda, para ficheros creados por el programador.

Constantes simbólicas (con nombre)

Supongamos que tenemos que hacer un programa en el que haya que escribir unas cuantas veces3.1415927. Es muy fácil que nos confundamos alguna vez al escribirlo. Así, al compilar el programa no recibiremos ningún mensaje de error aunque los resultados no serán correctos. Para evitar esto usamos lasconstantes simbólicas o constantes con nombre. No son nada más que un caso particular de la utilización de macros. Al definir una constante simbólica asignamos un nombre a la secuencia 3.1415927, y parece razonable utilizar el nombre PI. Por ejemplo:

#include <stdio.h>

#define PI 3.1415927

main()
{
 int radio, perimetro;

 radio = 20;
 perimetro = 2 * PI * radio;

 
 printf( "El perímetro es: %i", perimetro  );
}

De esta forma cada vez que el compilador encuentre el nombre PI lo sustituirá por 3.1415927.

A una constante no se le puede dar un valor mientras se ejecuta; no se puede hacer PI=20;. Sólo se le puede dar un único valor con #define, y sólo una vez (salvo que se utilice #undef y de nuevo #define). Tampoco podemos usar scanf para dar valores a una constante:

#define CONSTANTE 14

main()
{
 ...
 scanf( "%i", CONSTANTE );
 ...
}

eso equivaldría a:

 scanf( "%i", 14 );

Esto es muy grave, pues estamos diciendo que el valor que escribamos en la entrada de scanf se almacene en la posición 14 de la memoria, lo que puede bloquear el ordenador.

Las constantes se suelen escribir en mayúsculas, sólo se puede definir una constante por fila y no se añade";" al final.

Las constantes nos proporcionan una mejor comprensión del código fuente. Obsérvese el siguiente programa:

#include <stdio.h>

main()
{
 int precio;

 precio = (4 * 25 * 100) * 1.16;
 
 printf( "El precio total es: %i", precio  );
}

¿Quién entiende lo que quiere decir este programa? Es difícil, si no imposible. Hagámoslo de otra forma.

#include <stdio.h>

#define CAJAS   4
#define UNIDADES_POR_CAJA 25
#define PRECIO_POR_UNIDAD  100
#define IMPUESTOS  1.16

main()
{
 int precio;

 precio = (CAJAS * UNIDADES_POR_CAJA * PRECIO_POR_UNIDAD) * IMPUESTOS;
 
 printf( "El precio total es: %i", precio  );
}

Ahora se entiende mucho mejor. Si revisamos el penúltimo programa un tiempo más tarde ya no recordaremos qué significaba cada número. De esta segunda forma nos ponemos al día rápidamente.

También podemos definir una constante usando el valor de otras. Por supuesto, éstas deben estar definidas con anterioridad:

#include <stdio.h>

#define CAJAS   4
#define UNIDADES_POR_CAJA 25
#define PRECIO_POR_UNIDAD 100 
#define PRECIO_POR_CAJA  UNIDADES_POR_CAJA * PRECIO_POR_UNIDAD
#define IMPUESTOS  1.16

main()
{
 int precio;

 precio = ( CAJAS * PRECIO_POR_CAJA ) * IMPUESTOS ;
 
 printf( "El precio total es: %i", precio  );
}

0 comentarios:

Publicar un comentario

Aprende a Programar tus propias aplicaciones