Na aula passada, vimos um modelo simples para entender como computadores funcionam e como podemos programá-los. Na aula de hoje vamos chegar um passo mais próximo de programas de verdade, e estudar linguagens de programação e tipos de dados, bem por cima.
A partir do modelo da aula passada já podemos ter uma idéia de como se passa um programa para o computador executar. Primeiro, cria-se uma sequência de comandos (e dados) em endereços de memória fixos (para que a parte de recalcular M funcione), copiamos essas instruções para a memória do computador e mandamos o processador executá-las (por exemplo, ligando o processador). Isso é surpreendentemente parecido, dado a sua simplicidade, de como um computador funciona na vida real. No entanto, é óbvio que escrever um programa num modelo desses é bem difícil, pelos seguintes (dentre outros) motivos:
Para resolver esse tipo de problema, foram criadas linguagens de programação, que são formas mais inteligíveis (para pessoas) de especificarem as instruções e os dados que estão na memória de um computador mas que um computador consegue executar sem muita perda de performance.
Pra clareza de comunicação, todas as formas de se escrever um programa pra um computador executar são chamadas de linguagens de programação. Métodos de escrever programas que consistem imediatamente ou quase imediatamente em escrever código de máquina são chamados de linguagens de baixo nível. Esse é um programa em linguagem de baixo nível para calcular a média de vários valores:
inicio: add eax,[esi+ecx] cmp ecx,1 jle inicio div eax
Já linguagens que criam mais camadas de abstração entre o código executado pelo computador e o escrito pelo programador são chamadas linguagens de alto nível. Esse é um programa em uma linguagem de muito alto nível para calcular a média de vários valores:
def media(valores): return sum(valores)/len(valores)
Nesse curso trabalharemos com uma linguagem de alto nível, mas não muito alto nível, chamada C. Um programa C para calcular a média de vários valores pode ser:
double media(double[10] valores) { int i, m = 0; for (i = 0; i < 10; i = i+1) { m = m + valores[i] } return m/10 }
Ao longo do curso, esse programa fará mais e mais sentido para vocês.
Existem duas famílias de estratégias para executar programas escritos em linguagens de programação em computadores. A primeira, interpretação, é quando existe um programa já escrito, chamado interpretador, que lê arquivos texto com o código-fonte e executa as instruções. Quase todas as linguagens de pacotes estatísticos são interpretadas.
A outra estratégia, compilação, é quando um programa é usado para traduzir o código fonte em código de máquina. C é uma linguagem compilada. Isso significa que para executar um programa C, o caminho é algo como:
Esse arquivo executável pode ser executado em outras máquinas (com o mesmo sistema operacional e arquitetura) sem problemas, e sem a necessidade do compilador.
A linguagem C de programação foi criada na década de 70 por cientistas do bell labs para ser usada na programação do sistema operacional UNIX.
Vamos olhar para o programa exemplo e destrinchá-lo por partes,
#include <stdio.h> int main(int argc, char *argv[]) { printf("Bem vindo a MC102.\n"); return 0; }
O programa pode ser dividido em duas partes.
A primeira, o cabeçalho, nesse caso só tem a linha
#include <stdio.h>que diz que o programa quer usar as funções de entrada e saída da biblioteca padrão. Vocês não precisarão se preocupar com o significado dos comandos de include nesse curso.
O restante do programa é composto de declarações de funções e procedimentos. Uma função (ou procedimento) é um bloco de código que pode ser executado várias vezes de outros pontos do programa. Todo programa em C é estruturado através de funções, e sua execução gira em torno da função main. A função main tem sempre a mesma estrutura.
Uma declaração de função tem duas partes: a sua especificação dos tipos e o bloco de código relacionado. No caso da função main, nessa disciplina, declararemos ela sempre como
int main(int argc, char *argv[])Isso significa que ela retorna um valor inteiro (o primeiro "int") e recebe dois parâmetros, um inteiro chamado "argc" e um ainda não explicado chamado argv. O modelo para declarar funções arbitrárias em C é parecido com isso, e estudaremos mais tarde.
Um bloco de código em C é uma sequência de comandos, normalmente rodeados por "{" e "}" (mas em alguns casos essas chaves podem ser omitidas). Um comando C pode ser de vários tipos (atribuição, execução de procedimento, etc), mas sempre é terminado com um ";". Assim, as linhas
printf("Bem vindo a MC102.\n");e
return 0;constituem comandos.
O comando printf, que será estudado mais tarde, escreve coisas na tela, e e um dos comandos que sera usado nessa aula para fazer saida de dados.
Toda função é terminada por um comando "return", e a função main é normalmente terminada com o comando "return 0".
Toda linha de código em C é um comando, e alguns comandos são expressões. Um bom jeito de entender comandos e expressões é que comandos fazem coisas acontecer e expressões geram valores que podem ser usados em comandos ou outras expressões.
Até agora vimos três tipos de comando: comando para declarar funções, comando para imprimir coisas na tela e comando para retornar valores de funções. Um outro comando muito importante é o de atribuição
Expressões normalmente são coisas como a+b, a-b, etc, e normalmente manipulam valores que são eventualmente guardados em uma variável ou utilizados em comandos mais complexos. Uma boa coisa para se ter em mente
Um tipo de comando importante em C é a declaração de variável. Esse comando te dá um nome (variável) associado a um lugar na memória, onde você pode guardar um valor. Para utilizar uma variável em C, basta declarar o seu tipo e o seu nome; por exemplo,
int x;define uma variável inteira chamada x e
double f;define uma variável real chamada f. Não se esqueçam dos ponto-e-vírgulas no final das declarações! As declarações têm que ser as primeiras coisas dentro de um bloco de código.
Após rodar esses comandos, que devem sempre ser colocados no começo de qualquer bloco, você pode usar o valor guardado nas variáveis correspondentes ou definir novos valores para essas variáveis usando comandos de atribuição, como
x = 10 - 2;
Caso haja dúvidas sobre a ordem de execução de uma expressão, a melhor alternativa é colocar parênteses. O ideal são expressões da forma
(-b + sqrt(b*b - 4*a*c))/(2*a)que não permitem confusão na hora de interpretá-las.
Na próxima aula aprenderemos mais comandos e expressões com mais calma, e o que eles fazem e como funcionam.
Nomes de variáveis são palavras que começam com letras e são seguidas por letras, números ou _ (underline). Letras maiúsculas e minúsculas fazem a diferença. Evitem usar letras maiúsculas como nomes de variáveis.
Computadores fazem operações com vários tipos diferentes de dados. Internamente, todos esses tipos são representados de forma idêntica (como bits na memória), mas os seus programas devem manipulá-los de formas bem distintas. Para isso, as linguagens de programação tendem a usar o conceito de tipos de dados. Alguns tipos que serão bastante utilizados na linguagem de programação C são:
int | um número inteiro de 32 bits |
unsigned int | um número natural de 32 bits |
float | um número real com precisão de 32 bits |
double | um número real com precisão de 64 bits |
char | tanto pode ser um inteiro pequeno como um caracter de texto |
void | é um tipo virtual, nenhum valor é void |
Esses tipos são básicos no sentido de que quase todos os outros tipos que manipularemos ao longo desse curso podem ser representados como coleções desses tipos. Palavras, frases e arquivos de texto inteiros, por exemplo, podem ser representados como sequências de caracteres. Matrizes, vetores, e números complexos podem ser representados como sequências de valores com precisão simples ou dupla. Endereços de memória podem (mas não são!) ser representados por valores inteiros, e por aí vai.
Um inteiro é escrito, em C, como uma sequência de números, como 2, 4, 1234, etc. Números reais usam . (ponto) como separador (como 12.34 , 656.32222 , 3.14 , etc). Caracteres são escritos dentro de aspas simples, como 'a' ou 'b'.
Vocês notaram que eu indiquei explicitamente quantos bits são usados para números reais. Por que isso é importante?
Um computador pode manipular apenas um número finito de bits para fazer qualquer operação. Para a maior parte dos programas que faremos em sala de aula podemos ignorar o fato de que não podemos armazenar números arbitrariamente grandes (no caso de inteiros) ou precisos (no caso de números reais), mas é muito fácil cair em casos em que se estoura o limite de tamanho permitido para uma variável inteira ou o limite de precisão permitido para uma variável real, e precisa-se tomar cuidado com isso.
Existe muita pesquisa em como projetar algoritmos que fazem muitas contas e se mantém dentro da precisão permitida pelo computador. Por exemplo, ao trabalhar com probabilidades, é normal utilizar ln(P(x)) em vez de P(x) se você vai fazer muitas multiplicações (que, após calcular o logaritmo, viram somas), para evitar lidar com números muito próximos de zero (que acabam virando zero por causa da precisão finita).
Date: 2010-08-05 20:44:29 BRT
HTML generated by org-mode 6.21b in emacs 23