Preprocesador C++
Los preprocesadores son las directivas, que dan instrucciones al compilador para que procese previamente la información antes de que comience la compilación real.
Todas las directivas de preprocesador comienzan con # y solo pueden aparecer caracteres de espacio en blanco antes de una directiva de preprocesador en una línea. Las directivas de preprocesador no son sentencias de C++, por lo que no terminan en punto y coma (;).
Ya has visto un #include directiva en todos los ejemplos. Esta macro se utiliza para incluir un archivo de encabezado en el archivo de origen.
Hay varias directivas de preprocesador admitidas por C++ como #include, #define, #if, #else, #line, etc. Veamos directivas importantes −
El preprocesador #define
La directiva de preprocesador #define crea constantes simbólicas. La constante simbólica se llama macro y la forma general de la directiva es −
#define macro-name replacement-text
Cuando esta línea aparece en un archivo, todas las apariciones posteriores de macro en ese archivo serán reemplazadas por texto de reemplazo antes de compilar el programa. Por ejemplo −
#include <iostream> using namespace std; #define PI 3.14159 int main () { cout << "Value of PI :" << PI << endl; return 0; }
Ahora, hagamos el preprocesamiento de este código para ver el resultado suponiendo que tenemos el archivo de código fuente. Así que vamos a compilarlo con la opción -E y redirigir el resultado a test.p. Ahora, si revisa test.p, tendrá mucha información y en la parte inferior, encontrará el valor reemplazado de la siguiente manera −
$gcc -E test.cpp > test.p ... int main () { cout << "Value of PI :" << 3.14159 << endl; return 0; }
Macros similares a funciones
Puede usar #define para definir una macro que tomará argumentos de la siguiente manera −
Demostración en vivo#include <iostream> using namespace std; #define MIN(a,b) (((a)<(b)) ? a : b) int main () { int i, j; i = 100; j = 30; cout <<"The minimum is " << MIN(i, j) << endl; return 0; }
Si compilamos y ejecutamos el código anterior, esto produciría el siguiente resultado −
The minimum is 30
Compilación condicional
Hay varias directivas que se pueden usar para compilar partes selectivas del código fuente de su programa. Este proceso se denomina compilación condicional.
La construcción del preprocesador condicional es muy parecida a la estructura de selección 'si'. Considere el siguiente código de preprocesador −
#ifndef NULL #define NULL 0 #endif
Puede compilar un programa con fines de depuración. También puede activar o desactivar la depuración usando una sola macro de la siguiente manera −
#ifdef DEBUG cerr <<"Variable x = " << x << endl; #endif
Esto provoca el cerr sentencia a compilar en el programa si se ha definido la constante simbólica DEBUG antes de la directiva #ifdef DEBUG. Puede usar la declaración #if 0 para comentar una parte del programa de la siguiente manera −
#if 0 code prevented from compiling #endif
Probemos el siguiente ejemplo −
Demostración en vivo#include <iostream> using namespace std; #define DEBUG #define MIN(a,b) (((a)<(b)) ? a : b) int main () { int i, j; i = 100; j = 30; #ifdef DEBUG cerr <<"Trace: Inside main function" << endl; #endif #if 0 /* This is commented part */ cout << MKSTR(HELLO C++) << endl; #endif cout <<"The minimum is " << MIN(i, j) << endl; #ifdef DEBUG cerr <<"Trace: Coming out of main function" << endl; #endif return 0; }
Si compilamos y ejecutamos el código anterior, esto produciría el siguiente resultado −
The minimum is 30 Trace: Inside main function Trace: Coming out of main function
Los operadores # y ##
Los operadores de preprocesador # y ## están disponibles en C++ y ANSI/ISO C. El operador # hace que un token de texto de reemplazo se convierta en una cadena entre comillas.
Considere la siguiente definición de macro −
Demostración en vivo#include <iostream> using namespace std; #define MKSTR( x ) #x int main () { cout << MKSTR(HELLO C++) << endl; return 0; }
Si compilamos y ejecutamos el código anterior, esto produciría el siguiente resultado −
HELLO C++
Veamos cómo funcionó. Es fácil de entender que el preprocesador de C++ convierte la línea −
cout << MKSTR(HELLO C++) << endl;
La línea anterior se convertirá en la siguiente línea −
cout << "HELLO C++" << endl;
El operador ## se usa para concatenar dos tokens. Aquí hay un ejemplo −
#define CONCAT( x, y ) x ## y
Cuando CONCAT aparece en el programa, sus argumentos se concatenan y se usan para reemplazar la macro. Por ejemplo, CONCAT(HOLA, C++) se reemplaza por "HOLA C++" en el programa de la siguiente manera.
Demostración en vivo#include <iostream> using namespace std; #define concat(a, b) a ## b int main() { int xy = 100; cout << concat(x, y); return 0; }
Si compilamos y ejecutamos el código anterior, esto produciría el siguiente resultado −
100
Veamos cómo funcionó. Es fácil de entender que el preprocesador de C++ transforma −
cout << concat(x, y);
La línea anterior se transformará en la siguiente línea −
cout << xy;
Macros C++ predefinidos
C++ proporciona una serie de macros predefinidas que se mencionan a continuación −
Sr.No | Macro y descripción |
---|---|
1 | __LINE__ Contiene el número de línea actual del programa cuando se está compilando. |
2 | __ARCHIVO__ Contiene el nombre de archivo actual del programa cuando se está compilando. |
3 | __FECHA__ Este contiene una cadena del formato mes/día/año que es la fecha de la traducción del archivo fuente al código objeto. |
4 | __HORA__ Este contiene una cadena de la forma hora:minuto:segundo que es la hora en que se compiló el programa. |
Veamos un ejemplo para todas las macros anteriores −
Demostración en vivo#include <iostream> using namespace std; int main () { cout << "Value of __LINE__ : " << __LINE__ << endl; cout << "Value of __FILE__ : " << __FILE__ << endl; cout << "Value of __DATE__ : " << __DATE__ << endl; cout << "Value of __TIME__ : " << __TIME__ << endl; return 0; }
Si compilamos y ejecutamos el código anterior, esto produciría el siguiente resultado −
Value of __LINE__ : 6 Value of __FILE__ : test.cpp Value of __DATE__ : Feb 28 2011 Value of __TIME__ : 18:52:48
Lenguaje C