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 somente caracteres de espaço em branco podem aparecer antes de uma diretiva de pré-processador em uma linha. As diretivas de pré-processador não são instruções C++, portanto, não terminam em ponto e vírgula (;).
Você já viu um #include diretiva em todos os exemplos. Essa 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. Vamos ver diretivas importantes −
O pré-processador #define
A diretiva de pré-processador #define cria constantes simbólicas. A constante simbólica é chamada de macro e a forma geral da diretiva é −
#define macro-name replacement-text
Quando esta linha aparece em um arquivo, todas as ocorrências subsequentes de macro nesse 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. Então 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 forma −
$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 receberá o argumento da seguinte forma -
Demonstração ao 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; }
Se compilarmos e executarmos o código acima, isso produziria 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. Esse 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 cerr instruçã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 forma -
#if 0 code prevented from compiling #endif
Vamos tentar o seguinte exemplo -
Demonstração ao 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; }
Se compilarmos e executarmos o código acima, isso produziria 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 texto de substituição seja convertido em uma string entre aspas.
Considere a seguinte definição de macro -
Demonstração ao vivo
#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 produziria o seguinte resultado -
HELLO C++
Vamos ver como funcionou. É simples entender que o pré-processador C++ transforma 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 forma.
Demonstração ao vivo
#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 produziria 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++ predefinidos
C++ fornece uma série de macros predefinidas mencionadas abaixo -
Sr.Nº | 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__ Este contém uma string no formato mês/dia/ano que é a data da tradução do arquivo fonte 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 -
Demonstração ao 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; }
Se compilarmos e executarmos o código acima, isso produziria o seguinte resultado -
Value of __LINE__ : 6 Value of __FILE__ : test.cpp Value of __DATE__ : Feb 28 2011 Value of __TIME__ : 18:52:48
Linguagem C