3. COMPILAÇÃO E ESTRUTURA BÁSICA DE UM PROGRAMA EM C 3.1. Compilação de um Programa C O compilador C realiza a compilação do código-fonte de um programa em cinco etapas: edição, pré-processamento, compilação, montagem e ligação. Essas etapas de processamento são ilustradas na Figura 16. Figura 16: Processo de compilação de um programa C 3.1.1. Edição A etapa de edição consiste de um programa de edição para editar e/ou corrigir um programa C. Durante esta etapa os arquivos do programa C devem ser então armazenados em um dispositivo de armazenamento secundário, como por exemplo, o disco. Curiosidade Os arquivos dos programas C devem ter a extensão .c. 3.1.2. Pré-processamento A etapa de pré-processamento é responsável por modificar o código-fonte do programa lexicamente. É nesta etapa que ocorre a suspensão de espaços desnecessários, substituição de macros e a inclusão de outros códigos (através das diretivas de pré-processamento). Esta etapa gera um código chamado de unidade de compilação. Curiosidade É possível realizar apenas a etapa de pré-processamento, através do comando gcc. Para isso, basta utilizar o seguinte comando: gcc –E <nome_programa>.c (mostra a unidade de compilação no terminal). Pode-se usar também a opção –o par armazenar a saída em um arquivo (gcc –E <nome_programa>.c –o <nome_unidade>.e) 3.1.3. Compilação É na compilação que o compilador faz a análise sintática e semântica da unidade de compilação. Não havendo erro de sintaxe e de semântica o compilador gera o código assembly correspondente. Curiosidade A opção –S do gcc realiza a geração do código assembly e permite armazenar em um arquivo com a extensão .s (gcc –S <nome_programa>.c). 3.1.4. Montagem A etapa de montagem é responsável por gerar o código-objeto. Ou seja, é nessa etapa que os comandos assembly são transformados em linguagem de máquina. Curiosidade A opção –c do gcc realiza a geração do código-objeto e permite armazenar em um arquivo com a extensão .o (gcc –c <nome_programa>.c). 3.1.5. Ligação Essa é a etapa final, onde ocorre a combinação de todos os códigos-objetos que compõem um programa C. O resultado desta etapa é um código executável. 3.2. Estrutura de um Programa C Um programa C consiste em uma função ou várias funções, onde, a forma geral de uma função em C é a seguinte: <tipo de retorno> <nome da função>(<lista de parâmetro>) { instrução1; instrução2; ... instrução; return <valor>; } Um programa C precisa ter uma função principal, que deve ser chamada de main, para inicia a execução do programa. Curiosidade Em todo programa C deve existir uma função chamada main. E essa função marca o ponto inicial do programa e a execução do programa só termina quando a função main encerrar. A função main, retornar um valor inteiro e pode ou não possuir parâmetros. Inicialmente vamos considerar a estrutura da função main, sem parâmetro, como mostrado no Programa 1. Programa 1: Primeiro código de um programa C 1 2 3 4 5 6 #include <stdio.h> int main(void) { printf(“Meu primeiro programa!\n”); return 0; } A primeira linha do Programa 1 não é uma instrução da linguagem C (não tem ponto-e-vírgula no final), ela é uma diretiva de pré-processamento (#include <stdio.h>), necessária para o compilador verificar a referência à função printf. A diretiva de pré-processamento include é responsável por incluir um arquivo no código-fonte, antes da compilação. Ou seja, o compilador substitui a linha contendo essa diretiva pelo conteúdo de arquivos-cabeçalho antes de compilar o programa. Curiosidade As diretivas de pré-processamento é iniciada pelo símbolo # e não fazem parte da linguagem C e só servem para auxiliar no desenvolvimento do código-fonte. A função main está definida nas linhas 2 a 6. Na linha 4 existe uma chamada a função printf (O resultado dessa chamada é a impressão dos caracteres entre aspas – Meu primeiro programa!). O comando da linha 5, retorna para o sistema operacional o valor 0 (zero) e interrompe a execução do programa. 3.2.1. Biblioteca Padrão A linguagem C disponibiliza um conjunto de bibliotecas (conjunto de funções) para serem incorporadas aos programas dos usuários. Onde as funções dessas bibliotecas são declaradas em arquivos-cabeçalhos, que são organizados por finalidade ou área de aplicação. Curiosidade As funções de entrada (scanf) e saída (printf) são declaradas no arquivo-cabeçalho chamado stdio.h e as funções matemáticas são declaradas no arquivo-cabeçalho math.h. 3.2.1.1. Arquivos-cabeçalhos do Sistema Os arquivos-cabeçalhos do sistema contêm as declarações das variáveis e funções dos objetos armazenados na biblioteca padrão. Curiosidade Os arquivos-cabeçalhos do sistema são referenciados entre chaves angulares (< e >), para que o compilador interprete como uma referência a um arquivo-cabeçalho do sistema. Os arquivoscabeçalhos do sistema são criados durante a instalação do compilador. 3.2.1.2. Arquivos-cabeçalhos do usuário Os arquivos-cabeçalhos do usuário são declarações de funções e variáveis desenvolvidas pelo usuário (programador) e que ele deseja que elas sejam disponibilizadas para outros programas. Curiosidade O compilador interpreta uma referência a um arquivo-cabeçalho do usuário através de aspas duplas (“ “). 3.3. Comandos de Compilação O comando mais simples do compilador gcc, mostrado abaixo, realiza todas as etapas da compilação, bastando somente relacionar o código-fonte, do programa C, que quer compilar e gera um código executável com o nome a.out. gcc <nome_programa>.c Dica Compilando o programa com a opção de compilação –o (gcc <nome_programa>.c –o <nome_executavel>) faz o código executável ser armazenado em um arquivo executável. A Tabela 2 apresenta alguns dos comandos de compilação do gcc usados para compilar programas C. gcc gcc gcc gcc Tabela 2: Alguns comandos de compilação do compilador gcc. Comandos Descrição Compila o programa prog.c e gera prog.c um executável a.out. Compila o programa prog.c e os prog.c aux.c io.c códigos distribuídos aux.c e io.c e gera um executável a.out. Compila o programa prog.c e gera prog.c –o exe um executável exe. Compila o programa prog.c e os prog.c aux.c io.c –o exe códigos distribuídos aux.c e io.c e gera um executável exe. 3.4. Laboratório: Compilando o Primeiro Programa C Este laboratório tem como finalidade mostrar como pode ser feita a compilação de um programa C. Um programa em C é dividido em vários arquivos, que são usados para formar um único arquivo executável. Compilar um programa C significa transformar o código-fonte em uma linguagem que será entendida e interpretada pelo sistema computacional alvo. O objetivo deste laboratório é mostrar através de um exemplo, algumas maneiras de compilar um programa em C. 3.4.1. Programa Exemplo Digite o código-fonte apresentado no Programa 1, da seção 3.2, em um arquivo texto e salve com o nome primeiro_programa.c. O Programa 1, faz uso de uma biblioteca padrão (biblioteca de entrada/saída) stdio.h, necessária para o compilador verificar a referência à função printf, causando a impressão do argumento passado a essa função. Recomendação O código deve ser digitado da mesma forma, ou seja, todos os caracteres devem ser digitados da forma mostrada, respeitando o uso de maiúsculas e minúsculas e colocando o ponto e vírgula no final de cada instrução. Pois, é muito comum programadores iniciantes esquecerem os caracteres como: chaves, aspas e ponto e vírgula. Outros detalhes desse código serão discutidos apenas nos capítulos subsequentes. Dica Cuidado para que o nome do arquivo-fonte criado não tenha extensões escondidas. Alguns editores de texto (Windows) costumam colocar a extensão .txt no nome do arquivo, fazendo o arquivo ficar com o nome primeiro_programa.c.txt. 3.4.2. Compilação Em um terminal, e no mesmo diretório em que se encontra o arquivo primeiro_programa.c, digite o comando: gcc primeiro_programa.c –o primeiro_programa Esse comando ira compilar o código-fonte. E a compilação dever ocorrer sem mensagem de erro e o programa executável terá o nome primeiro_programa. Execute o programa, e observe a impressão da mensagem: “Meu primeiro programa!” no terminal, como mostra a Figura 17. Figura 17: Execução do primeiro programa C Dica Se o comando gcc não puder ser executado, é possível que o seu ambiente não esteja identificando o local onde o compilador está instalado. Geralmente o problema está relacionado à variável de ambiente (PATH). Curiosidade O Uso do ponto seguido da barra inclinada é usado para executar o programa, em sistemas em que o diretório local não faz parte do caminho-padrão dos arquivos executáveis (Linux). Mas em alguns sistemas como o Windows, basta digitar primeiro_programa. Exercícios 1. Descreva e explique cada etapa do processo de compilação. 2. Quais são as extensões do código-fonte, código-objeto e código assembly? 3. O que cada comando de compilação abaixo faz: a) b) c) d) e) f) gcc gcc gcc gcc gcc gcc –c programa_a.c programa_b.c –o programa_b.exe –E programa_c.c –S programa_d.c programa_e.o programa_f.s –o programa_f 4. O que será impresso pelo programa a seguir? 1 2 3 4 5 #include <stdio.h> int main(void){ printf(“Fundamentos de programação usando C”); return 0; } 5. Quantas funções são chamadas no interior da função main do programa da questão anterior? 6. Utilize o compilador gcc para gerar o assembly do programa a seguir: 1 2 3 4 5 6 #include <stdio.h> int main(void){ int x; x = 2; return 0; } 7. O seguinte programa pode ter um erro de tempo de execução em: 1 2 3 4 5 #include <stdio.h> int main(void){ printf(“Fundamentos de programação usando C”); return 0; } 8. Escreva um programa que imprima no terminal a seguinte saída: 1 2 3 4 5 6 7 8 9 9. A diretiva #include é: a) b) c) d) e) Uma instrução da linguagem C. Uma instrução do compilador gcc. Uma instrução do pré-processamento. Uma instrução do sistema operacional Uma instrução do editor de texto. 10. Os arquivos-cabeçalhos incluídos pela diretiva #include servem para: a) b) c) d) e) Auxiliar o compilador a compilar o código-fonte. Auxiliar o programador na escrita do programa C. Executar instruções. Incluir programas no código-fonte do programa C. Nomear arquivos escondidos.