De Objective Caml para C e C++/Introdução

A linguagem C é uma linguagem bastante simples, criada na década de 70 e pouco atualizada desde então. A linguagem C provê uma camada de abstração em cima do nível de linguagem de assemblagem. Essa camada é composta por tipos básicos (basicamente tipos numéricos), construtores de tipos simples, construções algorítmicas clássicas, e modularização funcional. Os principais pontos fortes da linguagem C são uma ampla difusão, a rapidez de execução dos programas compilados, e a possibilidade de interação com recursos de hardware. A principal desvantagem é que não possui conceitos de linguagens de programação mais avançados, o que pode penalizar a produtividade dos programadores naquela linguagem. A facilidade de acesso aos recursos de hardware, como a memória principal, é uma faca de dois gumes: permite programas muito rápidos, e falhas extremamente súteis (do tipo que se manifesta só em um determinado ambiente, em condições de uso muito específicas e que podem levar semanas a serem identificadas e corrigidas).

A linguagem C++ é uma linguagem derivada de C, e inclui novos paradigmas de programação como a orientação a objetos, tipos referências, polimorfismo paramétrico. C++ oferece muito mais recursos que C e é uma linguagem significativamente mais complexa e difícil de se dominar. Uma propriedade interessante é a sua compatibilidade quase total com a linguagem C, fazendo com que código C possa ser compilado por um compilador C++. Essa compatibilidade se estende até o código objeto: código C++ pode fazer uso de código desenvolvido em C. Embora a linguagem C++ seja bastante complexa, felizmente, não é necessário entender e dominar todos os recursos providos por essa linguagem para poder utilizá-la nos seus projetos de programação.

As linguagens C e C++ possuem ambas uma biblioteca padrão que provê algumas extensões práticas como a possibilidade de realizar entradas e saídas, de interagir com o sistema de arquivos. A biblioteca padrão de C oferece alguns poucos recursos de algoritmos e estruturas de dados. Em compensação a linguagem C++ possui uma biblioteca bem mais rica que

Diferente de Objective Caml, que pode-se interpretada ou compilada para bytecode e linguagem nativa, as linguagens C e C++ podem apenas ser compiladas. As diferentes atividades que compõem o processo de trabalho com essas linguagens são:

  • Edição: A grande maioria dos editores de texto possuem destaques de sintaxe para as linguagens C e C++. As duas principais são vi (e seus descendentes vim e gvim) e emacs (ou seu primo xemacs). Os editores de texto geralmente são configurados para oferecer destaque de sintaxe para a linguagem C quando o arquivo editado possui o prefixo .c e .h, e para a linguagem C++, quando o nome do arquivo é prefixado com ".C", ".cc", ".cpp" e ".hh".
  • Compilação: Existem diversos compiladores para essas linguagens. Os compiladores gcc e g++, além de serem gratuitos e de código aberto, podem ser utilizados em qualquer plataforma (Linux, Free BSD, Windows, MacOS).
  • Execução: O código é compilado em linguagem nativa da plataforma e só pode ser executado naquela plataforma.

Um primeiro programa em C++ editar

Esse primeiro exemplo vai ilustrar passo a passo as diferentes fases de criação de um programa. Iremos desenvolver em C++ um programa que imprime uma linha na saída padrão com o texto "ola." e que retorna o valor 0. Em Objective Caml, poderíamos programar isso com o seguinte código:

let _ =
  Printf.printf "ola.\n";
  0

O código seguinte é equivalente ao anterior, e fica mais próximo da versão C++:

let main () =
   Printf.printf "ola.\n";
   0

let _ =
   main()

Agora vamos para o C++... Você vai reparar que é um pouco mais complexo, mas fundamentalmente não é muito diferente. Para começar, devemos 'criar um programa'. Abra então um editor de texto e cria um novo documento.

  Inclui o seguinte texto no documento sendo editado:
#include <iostream>
int main ()
{
  std::cout << "ola.\n"
  return 0
}

Guarda o conteúdo do documento em um arquivo, por exemplo chamado exemplo1.cpp. Temos então nosso primeiro programa em C++! O que faz? Discutiremos isso depois, pois vamos partir logo para a segunda fase, que é a de 'compilação'.

Para isso, devemos utilizar o compilador C++. Podemos fazer isso através de um console de comandos. Abra então um console de comandos e digite o seguinte comando para compilar o arquivo:

g++ -ansi -Wall exemplo1.cpp

Esse comando é composto pelo nome do compilador (g++), duas opções (-ansi e -Wall) e o nome do arquivo a ser compilado. A opção -ansi instrui o compilador a verificar que você está seguindo as recomendações do padrão ANSI da linguagem C++. Isso garante a portabilidade de seu código. A opção -Wall é ainda mais importante, pois ela instrui o compilador a reportar avisos sobre erros possíveis no seu programa. A experiência prova que 99% dos erros possíveis são erros de fatos. Vale então a pena utilizar esse recurso para descobrir (pelo menos parte dos) erros que inevitavelmente são cometidos pelos programadores: 'errare humanum est'.

Deve aparecer a seguinte mensagem no console:

exemplo1.cpp: In function 'int main()':
exemplo1.cpp:6: error: expected `;' before '}' token

O compilador indica que na função int main(), há um erro, localizado na linha 6 (pode ser que você tenha introduzido linhas adicionais no seu editor, neste caso o número da linha onde ocorre esse erro poderá ser diferente).

O que aconteceu? Bom, a mensagem de erro é bastante clara: o compilador estava esperando o caractere ; antes do }. E o compilador está certíssimo, esquecemos de colocar um ponto e vírgula no final da linha 5 e quando encontrou } o compilador reparou essa falta! Corrija então esse erro no seu editor, salve novamente no arquivo e repete o comando de compilação.

Agora não há mais erro detectado pelo compilador. Vamos então executar o nosso programa... Mas onde está ele? Lista o conteúdo do diretório atual (o comando ls permite fazer isto) e observará a presença de um programa chamado a.out. Ao menos que seja instruído de outra forma, o compilador gera um programa em um arquivo com esse nome esquisito. Para gerar o programa com um outro nome, deve se utilizar uma opção específica do compilador, que é -o seguido do nome desejado. Por exemplo, se desejarmos chamar esse programa de exemplo1, o comando seria:

g++ -ansi -Wall exemplo1.cpp -o exemplo1

Para executar o programa, basta digitar no console o caminho até o arquivo que contem esse programa, por exemplo:

./exemplo1

Aparece então a seguinte mensagem:

ola.

Ufa!... Escrevemos o nosso primeiro programa em C++, e vimos como compilá-lo. Aprendemos três opções muito úteis do compilador g++, e verificamos que o compilador tem um papel importante para apoiar o desenvolvimento de programas corretos através da emissão de mensagens de erro e de avisos.

Explicações complementares editar

Para terminar essa introdução, precisamos ainda explicar como esse programa funciona. No processo começaremos a aprender algumas coisas da linguagem C++. Então, o que faz esse programa? Vamos incluí-lo novamente, dessa vez identificando as linhas com números:

1 #include <iostream>
2 int main ()
3 {
4   std::cout << "ola.\n";
5   return 0;
6 }

Nós não vamos entrar muito em detalhes aqui. A linha 1 faz referência a um arquivo chamado iostream, o qual faz parte da biblioteca padrão do C++. Este arquivo contém declarações de tipos e funções relacionadas com fluxos de entrada e saída (iostream abrevia input/output stream), ou seja com leitura e escrita de textos.

Em C e em C++, todas as linhas iniciando com o caractere # ('jogo da velha') são 'diretivas de pré-processamento'. Nessas linguagens, a compilação começa com uma fase dita de pré-processamento que realiza diversas operações de manipulação do código fonte como a inclusão de arquivos. Por exemplo, a diretiva #include resulte na inclusão do conteúdo de um arquivo.

As linhas 2 a 6 contém a definição de uma função, cujo nome é main (informações importantes sobre esse nome são dadas no final desta seção). Antes do nome da função vem o tipo do resultado da mesma: aqui é o tipo int que corresponde a números inteiros. Depois do nome da função, vem uma lista de parâmetros entre parênteses. Aqui a lista é vazia e não há parâmetros. main portanto é uma função que não tem argumentos, e que retorna um valor do tipo int. Em Caml esse tipo é denotado unit->int.

Depois da lista de parâmetros, vem o corpo da função, colocado entre chaves. Neste exemplo, o corpo dessa função é uma seqüência composta de dois comandos (ou instruções).

O primeiro comando (linha 4) aplica o operador de impressão C++, que se escreve << (menor menor). Esse operador é infixo e tem dois argumentos: o primeiro, a esquerda, é um fluxo de saída, no caso é std::cout, a saída padrão, o segundo argumento é o valor que será impresso, no caso é o texto "ola.\n". O resultado da aplicação deste operador é o próprio fluxo de saída. Assim, ele pode ser encadeado, como no exemplo seguinte:

std::cout << "Oi\n" << "Tudo bem?";

O segundo comando (linha 5) é uma instrução pré-definida da linguagem C++ que, tem um argumento, e instrui que a função deve terminar a sua execução e retornar o valor dado em argumento, no caso o valor 0.

Agora que explicamos cada linha do exemplo, devemos voltar ao nome da função: main. As linguagens C e C++ têm como convenção que a execução de um programa sempre inicia com a chamada da função chamada main. O valor que retorna a função main é comunicado ao sistema operacional e pode ser usado para informar da ocorrência ou não de algum problema. Por convenção, o valor 0 indica uma execução bem-sucedida.

Portanto, quando irá desenvolver um programa nessas linguagens, sempre deverá definir uma função com esse nome, que será o ponto inicial da execução desse programa.

Um primeiro programa em C editar

O programa C seguinte é equivalente ao programa C++ dado em exemplo no parágrafo anterior.

#include <stdio.h>
int main ()
{
  fprintf(stdout, "ola.\n");
  return 0;
}

Para experimentar a programação em C, abre um editor de texto, cópia o código dado e grave o mesmo em um arquivo chamado exemplo2.c. Para compilar esse arquivo e gerar um programa executável nomeado exemplo2, entre com o seguinte comando no console:

gcc -ansi -Wall exemplo2.c -o exemplo2

Então quais são as diferenças com o programa C++? Basicamente, são reduzidas ao uso de funções diferentes para realizar a impressão da mensagem ola. na saída padrão. Em C, utiliza-se uma função nomeada printf que é disponibilizada na biblioteca padrão através do arquivo stdio.h. Observe a similaridade com o comando Printf.printf da linguagem Objective Caml: o primeiro argumento é o fluxo de saída (stdout designa a saída padrão em C), e o segundo argumento é um texto a ser impresso. Em Objective Caml, como em C, esse texto pode ter diretivas de formatação de valores que são então passados como argumentos adicionais à função fprintf.

Lembre-se... editar

  • C e C++ não possuem interpretadores: Código nessas linguagens deve ser compilado para poder ser executado.
  • Um compilador para C é o programa gcc, para C++ pode usar o g++.
  • Um programa C ou C++ deve possuir uma função chamada main. Um programa sempre começa a se executar pela função main.