Você sabe quais os passos para se executar um programa em C++? Não? Então vamos olhar por baixo do capô para entender.
Tudo começa com o processo de compilação que gera um arquivo binário executável a partir do código fonte escrito pelo programador. Este processo envolve 3 programas: pré-processador, compilador e linker.
Diretivas de compilação
As diretivas são comandos que não são compilados e sempre iniciam com o caractere #.
Uma diretiva pode ser colocada em qualquer parte do programa e cada uma cumpre com uma tarefa (que veremos mais adiante), as principais são:
- #include
- #define
- #undef
- #ifdef
- #ifndef
- #if
- #else
- #elif
- #endif
- #pragma
Pré-processador
Seu papel é analisar o código-fonte e realizar modificações nele antes de passá-lo para o compilador. As diretivas dizem ao pré-processador se alguma parte do código deve ser compilada ou não, se o conteúdo de outro arquivo deve ser copiado para determinado local no código, se uma mensagem de erro será exibida em tempo de compilação, entre outras regras. Além de lidar com as diretivas ainda é responsável por remover comentários, substituir espaços em branco e junta linhas separadas por sequências de escape. Ufa!
Linguagem de máquina
A linguagem de máquina nada mais é do que uma sequência de bits (0s e 1s) decodificadas pela CPU na forma de instruções bem simples, tais como carregar dados na memória, somar dois valores, mover dados entre registradores.
Compilador
O compilador é o programa que traduz o código fonte em linguagem de máquina para que o computador entenda o que deve ser feito. O resultado desta tradução é um arquivo objeto com extensão .o ou .obj.
Linker
Mas você ainda não pode executar um arquivo objeto pois o conteúdo dele estará incompleto. Por exemplo, se você colocar um comando printf para exibir uma mensagem na tela, apesar de seu código ter sido compilado, o arquivo objeto gerado não saberá o que é printf, ele só possui uma referência a essa função, mas sua estrutura se encontra em uma biblioteca a parte. O linker é responsável linkar (ligar, unir) as instruções que estão em outras bibliotecas ou em outros arquivos objeto e gerar um único arquivo executável.
É importante notar que um executável não precisa conter todas as funções. Por exemplo, o Windows utiliza bibliotecas no mesmo formato de um executável, as famosas DLLs (Dynamic-link library). Essas bibliotecas contém códigos, dados, recursos e até outras bibliotecas a parte. A vantagem é que podem ser carregadas apenas uma vez na memória e utilizadas por outros programas que invocam suas funções, reduzindo o tamanho dos executáveis.
Diretivas de pré-processamento
Legal, agora que você já sabe como seu programa é compilado vamos dar uma olhada nas diretivas vistas acima.
#include
Para incluir um arquivo usamos a diretiva include. Ela diz ao compilador para copiar o conteúdo deste arquivo para alguma parte do seu código.
Existem certas coisas que você precisa saber quando for incluir um arquivo de cabeçalho:
- Para importar uma biblioteca em C é preciso indicar a extensão. Exemplo: #include <stdio.h>, #include <stdlib.h>
- Para importar uma biblioteca em C++ não é preciso indicar a extensão. Exemplo: #include <iostream>, #include <fstream>
- Você pode encontrar arquivos de cabeçalho que utilizam uma dessas extensões dependendo da convenção utilizada .h, .h++, .hh, .hxx e .hpp, sendo mais comum usar “.hpp” para C++ e “.h” para C.
- Existem dois modos de inclusão, entre colchetes angulares <> ou entre aspas “”
<> – o arquivo deve ser procurado no diretório padrão especificado pelo compilador
“” – o arquivo deve ser procurado no mesmo diretório do arquivo que contém a instrução #include.
#define
Serve para darmos nome a uma constante:
#define PI 3.1415926
Ou definir uma função simples:
#define DIV(x,y) ((x)/(y))
Toda vez que o pré-processador encontra o nome da constante ou a expressão no código realiza a substituição.
#undef
Remove um nome criado com #define e ignora as ocorrências subsequentes. Exemplo:
#undef PI
#undef DIV
#ifdef e #ifndef
Essas diretivas verificam a presença (#ifdef) ou ausência (#ifndef) de identificadores definidos com #define antes de compilar o bloco de código. São úteis para compatibilidade com versões anteriores da linguagem. Exemplo:
#ifdef PI
valor = valor * PI;
#endif
#if, #elif, #else e #endif
Compila blocos do código condicionalmente. Exemplo:
#if expressão_1
código
…
#elif expressão_2
código
…
#else expressão_n
código
…
#endif
#pragma
Os pragmas são específicos do computador ou do sistema operacional e podem variar de um compilador para outro. Se o compilador não identificar o nome da diretiva irá ignorar o #pragma.
Um do mais comuns é o #pragma once utilizado para indicar que o arquivo atual deve ser incluído apenas uma vez durante o processo de compilação.

