Pré-processador C ++

Os pré-processadores são as diretivas, que fornecem instruções ao compilador para pré-processar as informações antes do início da compilação real.

Todas as diretivas de pré-processador começam com # e apenas os caracteres de espaço em branco podem aparecer antes de uma diretiva de pré-processador em uma linha. As diretivas do pré-processador não são instruções C ++, portanto, não terminam em ponto-e-vírgula (;).

Você já viu um #includeem todos os exemplos. Esta macro é usada para incluir um arquivo de cabeçalho no arquivo de origem.

Existem várias diretivas de pré-processador suportadas por C ++ como #include, #define, #if, #else, #line, etc. Vejamos as diretivas importantes -

O pré-processador #define

A diretiva do pré-processador #define cria constantes simbólicas. A constante simbólica é chamada demacro e a forma geral da diretiva é -

#define macro-name replacement-text

Quando esta linha aparece em um arquivo, todas as ocorrências subseqüentes de macro naquele arquivo serão substituídas por texto de substituição antes que o programa seja compilado. Por exemplo -

#include <iostream>
using namespace std;

#define PI 3.14159

int main () {
   cout << "Value of PI :" << PI << endl; 

   return 0;
}

Agora, vamos fazer o pré-processamento deste código para ver o resultado assumindo que temos o arquivo de código-fonte. Portanto, vamos compilá-lo com a opção -E e redirecionar o resultado para test.p. Agora, se você verificar test.p, ele terá muitas informações e, na parte inferior, você encontrará o valor substituído da seguinte maneira -

$gcc -E test.cpp > test.p

...
int main () {
   cout << "Value of PI :" << 3.14159 << endl; 
   return 0;
}

Macros semelhantes a funções

Você pode usar #define para definir uma macro que terá o seguinte argumento -

#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;
}

Se compilarmos e executarmos o código acima, isso produzirá o seguinte resultado -

The minimum is 30

Compilação Condicional

Existem várias diretivas, que podem ser usadas para compilar partes seletivas do código-fonte do seu programa. Este processo é chamado de compilação condicional.

A construção do pré-processador condicional é muito parecida com a estrutura de seleção 'if'. Considere o seguinte código de pré-processador -

#ifndef NULL
   #define NULL 0
#endif

Você pode compilar um programa para fins de depuração. Você também pode ativar ou desativar a depuração usando uma única macro da seguinte maneira -

#ifdef DEBUG
   cerr <<"Variable x = " << x << endl;
#endif

Isso faz com que o cerrdeclaração a ser compilada no programa se a constante simbólica DEBUG foi definida antes da diretiva #ifdef DEBUG. Você pode usar a instrução #if 0 para comentar uma parte do programa da seguinte maneira -

#if 0
   code prevented from compiling
#endif

Vamos tentar o seguinte exemplo -

#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;
}

Se compilarmos e executarmos o código acima, isso produzirá o seguinte resultado -

The minimum is 30
Trace: Inside main function
Trace: Coming out of main function

Os operadores # e ##

Os operadores de pré-processador # e ## estão disponíveis em C ++ e ANSI / ISO C. O operador # faz com que um token de substituição de texto seja convertido em uma string entre aspas.

Considere a seguinte definição de macro -

#include <iostream>
using namespace std;

#define MKSTR( x ) #x

int main () {

   cout << MKSTR(HELLO C++) << endl;

   return 0;
}

Se compilarmos e executarmos o código acima, isso produzirá o seguinte resultado -

HELLO C++

Vamos ver como funcionou. É simples entender que o pré-processador C ++ vira a linha -

cout << MKSTR(HELLO C++) << endl;

A linha acima será transformada na seguinte linha -

cout << "HELLO C++" << endl;

O operador ## é usado para concatenar dois tokens. Aqui está um exemplo -

#define CONCAT( x, y )  x ## y

Quando CONCAT aparece no programa, seus argumentos são concatenados e usados ​​para substituir a macro. Por exemplo, CONCAT (HELLO, C ++) é substituído por "HELLO C ++" no programa da seguinte maneira.

#include <iostream>
using namespace std;

#define concat(a, b) a ## b
int main() {
   int xy = 100;
   
   cout << concat(x, y);
   return 0;
}

Se compilarmos e executarmos o código acima, isso produzirá o seguinte resultado -

100

Vamos ver como funcionou. É simples entender que o pré-processador C ++ transforma -

cout << concat(x, y);

A linha acima será transformada na seguinte linha -

cout << xy;

Macros C ++ Predefinidas

C ++ fornece uma série de macros predefinidas mencionadas abaixo -

Sr. Não Macro e descrição
1

__LINE__

Ele contém o número da linha atual do programa quando ele está sendo compilado.

2

__FILE__

Ele contém o nome do arquivo atual do programa quando ele está sendo compilado.

3

__DATE__

Ele contém uma string no formato mês / dia / ano que é a data da tradução do arquivo de origem em código-objeto.

4

__TIME__

Ele contém uma string no formato hora: minuto: segundo que é a hora em que o programa foi compilado.

Vamos ver um exemplo para todas as macros acima -

#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;
}

Se compilarmos e executarmos o código acima, isso produzirá o seguinte resultado -

Value of __LINE__ : 6
Value of __FILE__ : test.cpp
Value of __DATE__ : Feb 28 2011
Value of __TIME__ : 18:52:48