Pré-visualização11 páginas
Linguagens de Programação 1 - Notas de Aula Aviso: Essas notas de aula tem por finalidade orientar o professor no encaminhamento das aulas, a fim de não deixar assuntos fora da ordem planejada. A leitura deste material não reduz a necessidade de leitura da bibliografia recomendada. Última atualização em 28/02/12. 1. Paradigmas de Linguagens de Programação Existem muitas linguagens de programação, todas elas com características diferentes. Por vezes, muito diferentes. As linguagens no entanto, adotam técnicas comuns de programação, desenvolvidas de forma independente de uma linguagem conforme a área de Linguagens de Programação evolui. As linguagens de programação podem ser classificadas de muitas formas diferentes. Umas das formas de classificação é quanto ao paradigma de programação. Mas o que é um \u201cparadigma\u201d? A palavra paradigma pode significar muitas coisas. No contexto científico, costuma ser usada para um conjunto de teorias, padrões e métodos que juntos representam uma forma de organizar o conhecimento, ou seja, uma forma de ver o mundo [Budd91]. No contexto de linguagens de programação, podemos dizer de maneira bem simples que paradigma é um estilo. Porém estamos nos referindo a estilo numa conotação forte. Para serem chamados de paradigmas de programação, estilos precisam ser suficientemente diferentes e completos para serem considerados uma forma de ver o mundo. Autores diferentes classificam as linguagens de programação de formas diferentes. Apesar disso, é geralmente aceito que existem dois tipos principais de programação: (a) programação imperativa (ou procedural), de acordo com a qual os programas são construídos por meio de uma sequência de ordens - o programador escreve um procedimento que leva à solução de um problema; (b) programação declarativa (ou descritiva), de acordo com a qual os programas são construídos simplesmente pela descrição da solução de um problema - cabe ao compilador encontrar uma sequência de instruções que produz a solução declarada. Na programação declarativa, existem duas formas principais de se descrever soluções: (a) através de funções (conceito matemático de associação entre elementos de um conjunto domínio para um conjunto imagem) e (b) através de predicados (elementos sintáticos que permitem expressar relações entre elementos de conjuntos). Vale lembrar que uma função é um tipo especial de relação de associação. Assim, dadas essas duas categorias gerais distintas e o fato de que em uma delas, existem duas formas muito diferentes de descrever a solução de um problema, o autor deste texto considera que são três os paradigmas de programação: \u2022 programação imperativa (ou procedural) - em que programas são implementações de algoritmos (sequência de instruções que levam à solução de um problema); \u2022 programação funcional - em que programas são implementações de funções e \u2022 programação lógica - em programas são implementações de predicados (relações entre elementos de conjuntos diversos). É comum encontrar autores que classificam a Programação Orientada a Objetos como sendo um paradigma de programação. Essa classificação considera que o projeto de programas orientados a objetos segue conceitos de destaque suficiente para que esse estilo de programação seja classificado à parte da programação imperativa. Este texto se concentra na programação imperativa, apesar de apresentar conceitos que são independentes do paradigma de programação. Alguns conceitos em particular são melhor Notas de Aula de GCC105 - BCC e BSI - UFLA exemplificados através de suas implementações em linguagens funcionais como (LISP, ML, Haskell, etc.) e nesses casos daremos preferência a exemplos nessas linguagens. 2. Conceitos de Linguagens de Programação Este é o capitulo principal deste texto. Aqui são descritas características das linguagens de programação de uma maneira independente da linguagem de programação. São apresentados problemas relativos ao projeto de uma linguagem de programação juntamente com formas de resolvê-los. As várias soluções são comparadas para permitir que as linguagens de programação sejam entendidas de um ponto de vista mais amplo do que simplesmente como uma coleção de comandos e tipos de dados. Espera-se que as as informações apresentadas aqui permitam que leitor que sinta ambientado em qualquer linguagem de programação que venha a usar no futuro, em função de conhecer os conceitos que permitem a criação das várias facilidades que são proporcionadas de formas diferentes, por linguagens diferentes. 2.1 Tipos de Dados Algumas linguagens não tem o tipo de dado que você precisa, pode ser necessário implementá-lo (ex.: implementar listas ou árvores usando vetores). Algol68 permitia a declaração de novos tipos, um avanço significativo. Um tipo primitivo de dados é aquele que não pode ser decomposto em partes mais simples [Watt, 89]. Para tal classificação, considera-se a linguagem propriamente dita (e não suas bibliotecas). Para entender melhor essa definição, é necessário explicar melhor o conceito de \u201cser decomposto\u201d. Algumas informações são representadas por um grupo de outras informações (as partes mais simples). Se o programador não tem acesso a essas partes mais simples, dizemos que o tipo de dados é um tipo primitivo. Como os tipos de dados ainda não foram apresentados, vamos fazer uma analogia para dar um exemplo. Suponha que uma pessoa (talvez um aborígene no interior da Austrália) observa um carro e não percebe que ele é feito de várias peças interligadas. Para ele uma lanterna quebrada pode ser motivo para trocar o carro, já que ele entende o carro como uma só entidade. Se o programador só pode ver numa informação a informação como um todo (por causa da linguagem de programação), essa informação é de um tipo primitivo. O primeiro exemplo de um tipo de dados formado por partes mais simples é o ponto flutuante, visto na seção 2.1.2. 2.1.1 Inteiros Diferentes capacidades. Com ou sem sinal. Complemento de dois X Complemento de um. Complemento de dois requer circuito simples. Complemento de um permite duas representações para o zero. 2.1.2 Ponto Flutuante É uma representação para números racionais criada com o objetivo de manter a maior quantidade de bits significativos. Os bits que representam um ponto flutuante, são usados em três partes independentes: sinal, mantissa e expoente. prof. Bruno Schneider 2 Notas de Aula de GCC105 - BCC e BSI - UFLA A norma IEEE 754 estabelece 23 bits de mantissa e 8 de expoente para precisão simples; 52 bits de mantissa e 11 bits de expoente para precisão dupla. 2.1.3 Decimais Ponto fixo, útil em aplicações comerciais. Algumas máquinas tinham hardware próprio para esse tipo e representavam números como strings de bits, desperdiçando um pouco de espaço. Hoje em dia, costuma-se usar emulação desse tipo no software. 2.1.4 Booleanos Um único bit não é normalmente endereçável na memória. Tipos booleanos aumentam a legibilidade da linguagem (ver exemplo na seção de expressões booleanas). Algumas linguagens permitem que o valor de qualquer tipo seja testado. 2.1.5 Caracteres Existem vários sistemas de representação. Alguns usam tamanhos fixos e outros usam tamanhos variáveis. Considerar UNICODE como um sistema de codificação de caracteres é um erro comum. O próprio livro do Sebesta, afirma que o UNICODE é \u201cum conjunto de caracteres de 16 bits\u201d, o que é errado. Dizer que os caracteres são representados de acordo com a tabela ASCII é outro. 2.1.6 Ponteiros Proporcionam flexibilidade para outros tipos. Essa flexibilidade tem uma relação importante com o fato de que ponteiros podem \u201capontar para lugar nenhum\u201d (ex.: nil em Pascal, null em Java). Esse valor especial é quase sempre o número