C é uma linguagem de nível médio e precisa de um compilador para o converter num código executável de modo a que o programa possa ser executado na nossa máquina.
Como compilamos e executamos um programa em C?
Below são os passos que usamos numa máquina Ubuntu com compilador gcc.
- Criamos primeiro um programa C usando um editor e guardamos o ficheiro como nome de ficheiro.c
$ vi filename.c
- O diagrama à direita mostra um programa simples para adicionar dois números.
- >li>> depois compilá-lo usando o comando abaixo.
$ gcc –Wall filename.c –o filename
- A opção -Wall permite todas as mensagens de aviso do compilador. Esta opção é recomendada para gerar um melhor código.
A opção -o é utilizada para especificar o nome do ficheiro de saída. Se não utilizarmos esta opção, então é gerado um ficheiro de saída com nome a.out.
>ul>
$ ./filename
O que vai dentro do processo de compilação?
Compilador converte um programa em C num executável. Existem quatro fases para que um programa em C se torne um executável:
- Pré-processamento
- Compilação
- Montagem
- Link
Ao executar o comando abaixo, obtemos todos os ficheiros intermédios no directório actual juntamente com o executável.
$gcc –Wall –save-temps filename.c –o filename
A captura de ecrã seguinte mostra todos os ficheiros intermédios gerados.
Deixe-nos ver um a um o que estes ficheiros intermédios contêm.
Pré-processamento
Esta é a primeira fase através da qual o código fonte é passado. Esta fase inclui:
- Remoção de Comentários
- Expansão de Macros
- Expansão dos ficheiros incluídos.
- Compilação condicional
A saída pré-processada é armazenada no nome do ficheiro.i. Vamos ver o que está dentro do nome do ficheiro.i: usando $vi nome do ficheiro.i
Na saída acima, o ficheiro fonte é preenchido com lotes e muita informação, mas no final o nosso código é preservado.
Análise:
ul>
Compilação
p> O passo seguinte é compilar o ficheiro filename.i e produzir um; ficheiro de saída de compilação intermédia filename.s. Este ficheiro está em instruções de nível de montagem. Vamos ver através deste ficheiro usando $vi filename.s
O snapshot mostra que está em linguagem assembly, que o assembler pode compreender.
Assemblage
Nesta fase o nome do ficheiro.s é tomado como entrada e transformado em filename.o por assembler. Este ficheiro contém instruções ao nível da máquina. Nesta fase, apenas o código existente é convertido em linguagem de máquina, as chamadas de função como printf() não são resolvidas. Vamos ver este ficheiro usando $vi filename.o
Linking
Esta é a fase final em que todas as ligações de chamadas de função com as suas definições são feitas. O Linker sabe onde todas estas funções são implementadas. Linker também faz algum trabalho extra, adiciona algum código extra ao nosso programa, que é necessário quando o programa começa e termina. Por exemplo, existe um código que é necessário para configurar o ambiente, como por exemplo, passar argumentos de linha de comando. Esta tarefa pode ser facilmente verificada utilizando o nome de ficheiro $size.o e o nome de ficheiro $size.o. Através destes comandos, sabemos que a forma como o ficheiro de saída aumenta de um ficheiro objecto para um ficheiro executável. Isto é devido ao código extra que o linker adiciona com o nosso programa.