Você está na página 1de 118

Universidade Federal do Piau

Centro de Educao Aberta e a Distncia

Linguagens de
programao

Francisco Vieira de Sousa


Ministrio da Educao - MEC
Universidade Aberta do Brasil - UAB
Universidade Federal do Piau - UFPI
Centro de Educao Aberta e a Distncia - CEAD

Linguagens de Programao

Francisco Vieira de Sousa


PRESIDENTE DA REPBLICA Dilma Vana Rousseff Linhares
MINISTRO DA EDUCAO Aloizio Mercadante
GOVERNADOR DO ESTADO Wilson Nunes Martins
REITOR DA UNIVERSIDADE FEDERAL DO PIAU Jos Arimatia Dantas Lopes
PRESIDENTE DA CAPES Jorge Almeida Guimares
COORDENADOR GERAL DA UNIVERSIDADE ABERTA DO BRASIL Joo Carlos Teatini de S. Clmaco
DIRETOR DO CENTRO DE EDUCAO ABERTA E A DISTNCIA DA UFPI Gildsio Guedes Fernandes

COORDENADORES DE CURSOS
ADMINISTRAO Antonella Maria das Chagas Sousa
ADMINISTRAO PBLICA Fabiana Rodrigues de Almeida Castro
CINCIAS BIOLGICAS Maria da Conceio Prado de Oliveira
FILOSOFIA Zoraida Maria Lopes Feitosa
FSICA Miguel Arcanjo Costa
LETRAS PORTUGUS Jos Vanderlei Carneiro
LETRAS INGLS Lvia Fernanda Nery da Silva
MATEMTICA Jos Ribamar Lopes Batista
PEDAGOGIA Vera Lcia Costa Oliveira
QUMICA Davi da Silva
SISTEMAS DE INFORMAO Arlino Henrique Magalhes de Arajo

EQUIPE DE DESENVOLVIMENTO CONSELHO EDITORIAL DA EDUFPI


TCNICOS EM ASSUNTOS EDUCACIONAIS Ubirajara Santana Assuno Prof. Dr. Ricardo Alaggio Ribeiro (Presidente)
EDIO Roberto Denes Quaresma Rgo Des. Tomaz Gomes Campelo
PROJETO GRFICO Samuel Falco Silva Prof. Dr. Teresinha de Jesus Mesquita Queiroz
DIAGRAMAO Antonio F. de Carvalho Filho Prof. Dr. Jos Renato de Sousa
REVISO ORTOGRFICA Elizabeth Carvalho Medeiros Prof. Manoel Paulo Nunes
REVISO GRFICA Carmem Lcia Portela Santos Prof. Iracildes Maria Moura F Lima
Prof. Dr. Joo Renr Ferreira de Carvalho

S729l Souza, Francisco Vieira de


Linguagens de Programao/Francisco Vieira de Souza.
Teresina: UFPI/UAPI. 2009.
120p.

Inclui bibliografia
1 Caractersticas das Linguagens. 2 Variveis e Tipos.
3 Controle do Fluxo de Execuo. 4 Programao Orientada a
Objetos. I.
Universidade Federal do Piau/Universidade Aberta do Piau. II.
Ttulo.
CDD: 511.3

2013. Universidade Federal do Piau - UFPI. Todos os direitos reservados.

A responsabilidade pelo texto e imagens desta obra do autor. O contedo desta obra foi licenciado, temporria e
gratuitamente, para utilizao no mbito do Sistema Universidade Aberta do Brasil, atravs da UFPI. O leitor se compromete
a utilizar o contedo desta obra para aprendizado pessoal, sendo que a reproduo e distribuio ficaro limitadas ao mbito
interno dos cursos. A citao desta obra em trabalhos acadmicos e/ou profissionais poder ser feita, com indicao da fonte.
A cpia desta obra sem autorizao expressa, ou com intuito de lucro, constitui crime contra a propriedade intelectual, com
sanes previstas no Cdigo Penal.
proibida a venda deste material.
Este texto destinado aos estudantes do programa de Educao a
Distncia da Universidade Aberta do Piau (UAPI), vinculada ao consrcio
formado pela Universidade Federal do Piau (UFPI); Universidade Estadual
do Piau (UESPI); Instituto Federal de Educao, Cincia e Tecnologia do
Piau (IFPI); com apoio do Governo do estado do Piau, atravs da Secretaria
de Educao. O texto composto de quatro unidades, contendo itens e
subitens que discorrem sobre as Linguagens de Programao, evidenciando
como estas estruturas podem ser utilizadas no estudo da Informtica.
Na Unidade 1, so estudadas as principais caractersticas que uma
linguagem de programao deve apresentar para que seja considerada uma
boa linguagem. A unidade tem incio com a justificativa da necessidade de se
estudar as Linguagens de Programao e termina com uma discusso sobre
os principais paradigmas atualmente considerados.
Na Unidade 2, so analisadas as variveis e os tipos de dados,
buscando entender os diversos atributos que as variveis tm, envolvendo a
vinculao que a associao entre as variveis e seus atributos. Os tipos
de dados tambm so analisados luz da notao matemtica, j de domnio
pblico.
Na Unidade 3, se analisa o controle do fluxo de execuo dos
programas nos nveis: de expresso, instruo e de subprogramas, finalizando
com um estudo sobre corrotinas.
Na Unidade 4, se analisam os tipos abstratos de dados e como eles
podem ser implementados em Ada, C++ e Java. Em seguida, feito um
estudo sobre a Programao Orientada a Objetos, tanto do ponto de vista
terico, quanto prtico.
UNIDADE 1
11 CARACTERSTICAS DAS LINGUAGENS

Introduo..................................................................................1 1
Por que estudar LP?...................................................................1 1
Caractersticas das linguagens de programao.........................1 2
O desenvolvimento de software................................................12
O processo de traduo das linguagens.....................................16
Anlises lxica e sinttica das LPs..............................................23
Paradigmas das linguagens de programao.............................27

UNIDADE 2
35 VARIVEIS E TIPOS DE DADOS

Introduo..................................................................................35
Atributos de uma varivel..........................................................3 6
Tipos de dados...........................................................................4 6
Equivalncia de tipos.................................................................57

UNIDADE 3
35 CONTROLE DE FLUXO

Introduo..................................................................................65
Controle de execuo em nvel de expresses...........................65
Controle de fluxo em nvel de instrues...................................7 2
Controle do fluxo em nvel de subprogramas............................81
UNIDADE 4
96 ABSTRAO DE DADOS

Introduo..................................................................................97
O conceito de abstrao.............................................................97
O conceito de encapsulamento..................................................98
Tipos de dados abstratos definidos pelo usuro......................100
Progamao orientada a objetos..............................................106
Herana.....................................................................................107
Poliformismo............................................................................110
Classes Abstratas......................................................................110

REFERNCIAS......................................................................115
UNIDADE 1
Caractersticas das Linguagens

Resumindo
O objetivo principal desta Unidade apresentar os conceitos bsicos das Linguagens de
Programao, buscando capacitar o aluno na avaliao e comparao de LPs. comum ver em
fruns de programao debates de desenvolvedores defendendo sua linguagem preferida,
levantando algumas caractersticas da linguagem, outras vezes, apenas dizendo que a LP melhor,
sem especificar suas vantagens e desvantagens, sem apresentar as propriedades desejveis em uma
LP. Imaginamos que em um mundo global competitivo, no devemos nem podemos nos limitar a
uma nica linguagem de programao. necessrio ampliar o leque de opes, aprendendo as
caractersticas bsicas e os conceitos em que elas so implementadas. As caractersticas mudam
muito entre as LPs e estaria relacionado, por exemplo, a sua sintaxe e recursos e isso muda
rapidamente, levando a um estudo constante por parte dos desenvolvedores. J os conceitos e
metodologia se modificam a uma velocidade bem menor. Logo o profissional que tenha uma
maior habilidade em aprender rapidamente uma nova linguagem possui maiores chances de
sucesso nesta rea.
CARACTERSTICAS
DAs LINGUAGEns

Introduo

As LPs (Linguagens de Programao) so destinadas a serem usadas


pelas pessoas para expressar um processo atravs do qual um computador
pode resolver um problema. a forma de comunicao entre as pessoas e
o computador, quando elas desejam que ele execute determinadas tarefas,
necessrias para a soluo de determinados problemas.

Por que estudar LP?

Existem vrios motivos que exigem que os estudantes de Computao


conheam, com profundidade, as caractersticas e princpios que as
linguagens de programao devem apresentar e como so implementadas.
Entre eles, podem ser citados:

1. Maior habilidade em resolver problemas: uma maior compreenso


de uma LP pode aumentar nossa habilidade em pensar em como
atacar os problemas, tanto melhor se dominarmos os vrios
modelos de LPs.
2. Melhor uso de uma LP: a compreenso das funes e
implementao das estruturas de uma LP, nos levam a us-la de
forma a extrair o mximo de sua funcionalidade e eficincia.
3. Melhor escolha de uma LP: o conhecimento das caractersticas
das linguagens permite aos profissionais da rea de software,
escolher a que seja adequada soluo desejada para um
determinado tipo de problema.
4. Maior facilidade em aprender novas LPs: o conhecimento dos

Caractersticas das Linguagens 11


conceitos chaves comuns s LPs provoca maior facilidade no
aprendizado de novas linguagens.
5. Melhor projeto de LPs: o conhecimento de novas linguagens de
interfaces de sistemas, extenso de LP via operadores e tipos de
dados, permite melhores projetos de novas linguagens.

Caractersticas das linguagens de programao

As caractersticas desejveis em uma linguagem de programao tm


muito a ver com a aplicao que se tem em mos. No entanto, as linguagens
devem obedecer a alguns critrios que devem ser comuns a todas elas. O
conhecimento destes critrios e propriedades o objetivo principal deste
estudo e o tema desta seo.

Legibilidade

Esta caracterstica est relacionada com a facilidade com que um


programador l e entende rapidamente o cdigo de um programa. Quanto
mais fcil for ler um programa, mais fcil ser entender o cdigo e tambm
descobrir erros na programao. Uma LP com baixa legibilidade torna o seu
aprendizado mais difcil. Vejamos alguns exemplos:
Linguagens que usam Goto normalmente reduzem a legibilidade
porque nesse tipo de programao, os programas possuem fluxo
de controle e no obedecem a padres regulares. Tornando difcil
acompanhar e entender o que eles fazem.
Uso de mesmo vocbulo da LP para denotar diferentes
comportamentos dependendo do contexto prejudicial
legibilidade e entendimento da LP.
Ex: VISUAL BASIC:
- Uso do operador = com sinal de atribuio e comparao.
- Chamada funes e procedimentos com passagem de
parmetros. De acordo com o contexto necessrio o uso de (.

Ex: C/C++:
- Uso do * denota diversas coisas, como sinal multiplicador,
passagem por referncia, declarao de ponteiros.

12 unidade 1
Efeitos colaterais so prejudicais legibilidade. Eles causam
mudanas adicionais no estado do programa durante a avaliao
de uma determinada expresso ou a execuo de um comando
ou subprograma.
Ex: VISUAL BASIC:
- A no necessidade de informar os parmetros aos procedimentos
e funes, passagem por valor ou referncia. Adotando como
padro passagem por referncia, podendo ocasionar efeito
colateral indesejvel.

Ex: Marcadores de blocos de comandos como o begin end (Pascal


e Delphi) e o { } de C/C++ e JAVA, tambm podem causar confuses na
leitura do programa quando existem vrios comandos de repetio e seleo
aninhados. Alm disso, a no obrigatoriedade de usar um marcador especfico
para indicar onde o comando if do C se encerra, possibilita a escrita de
comando ifs aninhados, difceis de serem entendidos.
Ex: Algumas LPs adotaram postura altamente questionvel com
relao legibilidade. FORTRAM, por exemplo, permite que identificadores
especiais como DO, END, INTEGER e REAL sejam tambm nomes de
variveis.

Redigibilidade

A redigibilidade est relacionada com a facilidade com que um


programador codifica programas. A redigibilidade de programas pode conflitar
com a legibilidade. Por exemplo, a linguagem C permite a codificao de
comandos complexos, mas podem no identificar de maneira muito clara a
sua funcionalidade.
As LPs com tipos de dados limitados requerem o uso de estruturas
complexas, o que acaba dificultando a codificao de programas. A falta de
declarao recursiva e ponteiro em Visual Basic acaba limitando o seu uso
para implementar programas com uso de estruturas de rvores, listas e etc.
Outro ponto de falta de redigibilidade em Visual Basic est relacionado
com a declarao de variveis, onde no possvel declarar vrias variveis
do mesmo tipo, especificando o tipo somente uma vez.

Caractersticas das Linguagens 13


Confiabilidade

Essa propriedade se relaciona Aos mecanismos fornecidos pela LP


para incentivar a construo de programas confiveis. LPs que requerem
a declarao de dados permitem verificar, automaticamente, erros de tipos
durante a compilao ou execuo. LPs que possuem mecanismos para
detectar eventos indesejveis (Tratamentos de Erros) e especificar respostas
adequadas a tais eventos permitem construo de programas mais confiveis.

Eficincia

De acordo com as demandas por recursos de um tipo de aplicao,


certas LPs so mais recomendadas, e outras no devem ser usadas. Aplicao
de automao em tempo real, por exemplo, normalmente requerem o uso
de LPs que minimizem o tempo de execuo e de acesso aos dispositivos
perifricos, bem como o consumo de especo de memria.
Por exemplo, PASCAL, JAVA, VISUAL BASIC exigem que os ndices
de vetores sejam verificados em todos os acessos durante a execuo dos
programas. Isso implica na necessidade de fazer um teste antes de qualquer
acesso aos vetores. Por outro lado, como o C no exige este tipo de teste, o
cdigo gerado tem um desempenho melhor.
Em contrapartida, o fato de C no verificar os ndices de vetores
provoca alguma perda na confiabilidade de programas codificados nela. Pode
acarretar acesso a espao de memria erradamente, tornando a execuo do
programa imprevisvel. comum a quem programa em C, testar o programa
com sucesso, e, ao desligar a mquina e testar novamente, ocorrer erros.
Isso acontece devido coincidncia do acesso memria, de forma errada.
Na realidade, C uma linguagem para desenvolvedores que sabem o que
esto fazendo.

Facilidade de aprendizado

O programador deve ser capaz de aprender a linguagem com


facilidade. LPs com muitas caractersticas e mltiplas maneiras de realizar a
mesma funcionalidade, tendem a ser mais difceis de aprender. Alm disso,
outro aspecto negativo causado pelo excesso de caractersticas o fato de
levar os programadores a conhecerem apenas uma parte da linguagem, o

14 unidade 1
que torna mais difcil a um programador entender o cdigo produzido por
outro.

Ortogonalidade

Este termo diz respeito capacidade da LP permitir ao programador


combinar seus conceitos bsicos, sem que se produzam efeitos anmalos
nessa combinao. Assim, uma LP to mais ortogonal quanto menor for o
numero de excees aos seus padres regulares.
LPs ortogonais so interessantes porque o programador pode prever,
com segurana, o comportamento de uma determinada combinao de
conceitos. Isso pode ser feito sem que se tenha de implementar testes para a
averiguao do uso combinado de dois ou mais conceitos, ou mesmo, buscar
na especificao da LP se existe alguma restrio quela combinao.
A falta de ortogonalidade diminuiu o aprendizado da LP e pode
estimular a ocorrncia de erros de programao.
Ex: A no necessidade de declarao de variveis no Visual Basic
(default tipo variant); no permitir declarao de vrias variveis de mesmo
tipo, na mesma linha (default por referncia); permitir no especificar
passagem de valor ou referncia; permitir no especificar o escopo de
procedimentos e funes (default public).

Reusabilidade

A reusabilidade a possibilidade de reutilizao do mesmo cdigo


para diversas aplicaes. Quanto mais reusvel for um cdigo, maior ser
a produtividade de programao, uma vez que, na construo de novos
programas, bastar utilizar e, eventualmente, adaptar cdigos escritos
anteriormente sem que se faa necessrio reconstru-los. A grande maioria
das LPs permite reuso de cdigo atravs da modularizao por meio das
bibliotecas de subprogramas. Por exemplo, em Visual Basic, permite ao
programador modularizar o seu cdigo por mdulos ou classes e ainda
permite programao de dll e criao de componentes.

Modificabilidade

Refere-se s facilidades oferecidas pela LP para possibilitar ao

Caractersticas das Linguagens 15


programador alterar o programa em funo de novos requisitos, sem que
tais modificaes impliquem mudanas em outras partes do programa.
Exemplo de mecanismos que proporcionam boa modificabilidade so o uso
de constantes simblicas e a separao entre interface e implementao na
construo de subprogramas e tipos de dados abstratos.

Portabilidade

altamente desejvel que programas escritos em uma LP se


comportem da mesma maneira, independentes da ferramenta utilizada para
traduzi-los para a linguagem de mquina ou da arquitetura computacional
(hardware ou sistema operacional) sobre a qual esto sendo executados.
Dessa maneira, um mesmo programa ou biblioteca pode ser utilizado
em vrios ambientes e diferentes situaes, sem que seja necessrio
despender tempo de programao para reescrev-los ou adapt-los ao novo
ambiente de traduo ou execuo.

O desenvolvimento de software

Muitas mudanas, algumas radicais, aconteceram de forma rpida na


histria da computao, e, com o barateamento dos custos dos equipamentos
de computao, grande parte da importncia inicialmente atribuda ao
hardware passou para o software. Mquinas mais complexas e poderosas
exigem programao mais sofisticada, para que o seu potencial possa ser
aproveitado, e a produo de software hoje fundamental para virtualmente
qualquer espcie de atividade humana.
O ciclo de vida a seguir um dos diversos modelos que nos auxiliam
a compreender essa complexa atividade, e descreve, de forma simplificada,
as fases da histria de um programa:
Especificao de requisitos: nesta fase se procura definir com
clareza qual o problema considerado, e que caractersticas
deve ter uma soluo computacional (um sistema de hardware
e software adequados), para que essa soluo seja satisfatria
para a aplicao e o usurio.
Projeto global: nesta fase, procura-se definir, em linhas gerais,
como deve ser o software a ser construdo, para estabelecer a
viabilidade de sua construo e de sua utilizao nas condies

16 unidade 1
reais. nesta fase que deve ser escolhida a linguagem (ou
possivelmente as linguagens) de programao a utilizar.
Codificao: Nesta fase, o software efetivamente escrito em
uma ou mais linguagens escolhidas para isso.
Validao: nesta fase, o sistema testado, ou de alguma outra
forma examinado, para que se tenha uma garantia de seu
funcionamento satisfatrio.
Utilizao e evoluo: nesta fase, o sistema finalmente preenche
seus objetivos. Se existem, so ento descobertos erros e
problemas que, de alguma forma, tornam o sistema inadequado
para o uso pretendido. So tambm examinadas possibilidades
de alterao e extenso do sistema que visam torn-lo mais
adequado para a aplicao, cujas necessidades j podem ser
diferentes daquelas consideradas na fase de especificao de
requisitos. As alteraes a serem feitas constituem o que se
chama de manuteno ou evoluo do software.

Naturalmente, cada uma das fases mencionadas pode ser vrias


vezes repetidas, at que o produto final seja considerado satisfatrio. Quanto
mais cedo um erro for descoberto, mais simples e barata sua correo, e
por essa razo, importante que os erros sejam descobertos o mais cedo
possvel, nas fases iniciais do ciclo de vida.
Note-se que a escolha da linguagem de programao influi,
decisivamente, apenas em duas das fases do ciclo apresentado: a fase de
codificao, onde o programa escrito na linguagem, e a fase de evoluo/
manuteno, em que o programa alterado, atravs da introduo ou
substituio de trechos de cdigo escritos na linguagem. Nestas fases,
portanto, que defeitos e qualidades de uma linguagem de programao se
tornam aparentes.
Naturalmente, uma linguagem usada para programao de prottipos
no precisa exatamente das mesmas qualidades de uma linguagem
de programao de uso geral. Em alguns casos, prottipos podem ser
construdos em linguagens como Prolog ou Lisp, linguagens para as quais
legibilidade e eficincia no foram caractersticas dominantes de projeto;
posteriormente, se necessrio, verses definitivas podem ser construdas em
outras linguagens mais adequadas.

Caractersticas das Linguagens 17


Outras qualidades a serem consideradas em linguagens de
programao esto listadas a seguir.
Eficincia do programa compilado: a estrutura da linguagem
facilita o processo de gerao e otimizao de cdigo, permitindo
a construo de compiladores que gerem cdigo objeto que faa
uso eficiente dos recursos de mquina disponveis.
Eficincia do processo de compilao: a estrutura da linguagem
facilita o processo de compilao, permitindo a construo
de compiladores e ambientes de programao em que seja
mais eficiente o processo de desenvolvimento de software na
linguagem.
Disponibilidade de ferramentas: existem
compiladores, interpretadores, ambientes de
programao e de desenvolvimento amigveis,
adequados para a linguagem nas mquinas
em que a implementao deve ser realizada.
Alm disso, essas ferramentas devem poder ser
adaptadas a casos particulares, permitindo a
mxima eficincia em cada caso. Por exemplo,
os compiladores devem ter opes de compilao
que permitam gerar o melhor tipo de cdigo objeto
para cada aplicao.
Disponibilidade de bibliotecas: existem
bibliotecas de software de uso geral e de uso
especfico para a aplicao, que permitem a
utilizao de software j escrito, dispensando a
necessidade de sua construo. Essas bibliotecas
podem ser de texto fonte na linguagem, ou
de cdigo pr-compilado, escrito em qualquer
linguagem, mas que possa ser ligado ao cdigo
escrito na linguagem.

O processo de soluo de um problema


utilizando um programa de computador pode ser
Figura 1 3. O processo de soluo de um
pensado como o grfico mostrado na Figura 1.3 .
problema.
Na figura, mostrado o problema de forma
ainda confusa e que deve ser analisado atravs de

18 unidade 1
uma linguagem de especificao formal, gerando uma especificao que vai
ser implementada em alguma linguagem de programao.
Existem muitas linguagens de especificao formal. Entre elas,
podem ser citadas VDM, Lotos, Z, Redes de Petri e outras, dependendo da
rea em que o problema a ser resolvido se insere. A especificao formal vai
ser implementada em alguma linguagem de programao. A escolha desta
linguagem depende da experincia do programador e do conhecimento que
ele tem sobre a adequao das linguagens a cada tipo de problema. Deve
ser salientado, no entanto, que esta soluo representa uma soluo ideal e
ainda um processo em evoluo e difcil de ser bem realizado.
O objetivo principal de um programa de computador que ele seja
correto, ou seja, que faa apenas a tarefa para a qual foi projetado e de forma
correta. Esta exigncia tem se tornado cada vez mais presente, medida
que os problemas se tornam, a cada dia, mais complexos e difceis de
serem resolvidos. Lembremos que o homem, atualmente, controla reatores
nucleares e naves interplanetrias, e que cirurgias de alto risco podem ser
realizadas por robs. Isto significa que, inicialmente, os programas devem
ser corretos e depois apresentar um bom desempenho.
Enquanto o desenvolvimento de provas matemticas da corretude
de programas no for completamente dominado, uma soluo alternativa tem
sido a submisso do programa a testes de validade. Esta tcnica tem sido
empregada com relativo sucesso, para programas que no tenham grande
exigncia quanto necessidade de sua corretude. A escolha de bons testes
tem sido uma rea importante de pesquisa, lembrando que, os testes no
provam, matematicamente, a ausncia de erros; eles acusam a presena
deles para determinados casos, mas no para todos os casos possveis de
entrada de dados.

O processo de traduo das linguagens

Uma linguagem de programao pode ser convertida ou traduzida em


cdigo de mquina, por compilao ou interpretao. Ambas representando
algum processo de traduo.

O processo de compilao

A compilao pode ser realizada de forma pura, onde o programa

Caractersticas das Linguagens 19


totalmente analisado e traduzido por outro programa conhecido como
compilador, para um programa em linguagem de mquina. O compilador
constitudo pelos analisadores lxico, sinttico e semntico, que utiliza
uma tabela de smbolos para realizar o processo de traduo. Esta tabela
frequentemente consultada pelos analisadores durante o processo de
traduo. Os analisadores lxicos e sintticos sero vistos, com um pouco
mais de detalhes, ainda nesta unidade. O programa traduzido em linguagem
de mquina pode ser armazenado em alguma mdia, e ser executado em
outra oportunidade, e possivelmente, por outra mquina. Esse processo de
compilao pura est mostrado graficamente na Figura 1.4 a seguir.

Figura 1.4. Processo de compilao de um programa.

20 unidade 1
O processo de interpretao pura

Por outro lado, se o texto do programa for sendo traduzido, medida


que vai sendo executado num processo de traduo de trechos seguidos
de sua execuo imediata, ento, diz-se que o programa foi interpretado e
que o mecanismo utilizado para a traduo um interpretador. Programas
interpretados so, geralmente, mais lentos que os compilados, mas so
tambm mais flexveis, j que podem interagir com o ambiente, mais facilmente.
Esse processo, conhecido como interpretao pura, est mostrado na Figura
1.5, a seguir.

Figura 1.5. Processo de interpretao pura

O processo de interpretao hbrida

Embora haja essa distino entre interpretao e compilao, as


coisas nem sempre so to simples como parecem. Existem linguagens
onde o processo de implementao uma mistura entre os dois mtodos,
ou seja, h uma traduo inicial para um cdigo intermedirio e este cdigo
executado por um interpretador. Este mtodo hbrido tem a vantagem
de que, no processo de traduo do cdigo fonte para a representao
intermediria, os erros sintticos so detectados e corrigidos, fazendo com
que a representao intermediria seja um cdigo isento destes tipos de
erros.
A linguagem Java utiliza atualmente esta metodologia. Um compilador
traduz o cdigo em Java para o cdigo intermedirio (e portvel) da JVM (Java
Virtual Machine), conhecido como bytecode. Os bytecodes so executados
nos diversos browsers ou navegadores atravs de seus interpretadores.

Caractersticas das Linguagens 21


De forma grfica, esse procedimento est mostrado na Figura 1.6, a
seguir.

Figura 1 6. O processo de interpretao hbrida

Existem tambm outras formas de interpretar, em que os cdigos-


fontes, ao invs de serem interpretados linha-a-linha, tm blocos compilados
para a memria, de acordo com as necessidades, o que aumenta o
desempenho dos programas quando os mesmos mdulos so chamados
vrias vezes. Essa tcnica conhecida como JIT.
As JVMs originais interpretavam esse cdigo de acordo com o cdigo
de mquina do computador hospedeiro. Porm, atualmente, elas compilam
segundo a tcnica JIT o cdigo JVM para cdigo hospedeiro.
Deve ser salientado, no entanto, que as diferenas entre interpretadores
e compiladores no podem ser reconhecidas externamente com facilidade.
Em geral, o interpretador mais lento, uma vez que alguns passos a serem
realizados durante a execuo de um programa, notadamente, a busca de
instrues e a anlise de cada uma destas instrues so repetidas cada

22 unidade 1
vez que uma nova instruo for executada; no caso do compilador, isso
no necessrio. Adicionalmente, possvel adaptar o cdigo gerado por
um compilador para cada comando, de acordo com seu contexto, tirando
proveito de diferenas que no podem ser tratadas com a mesma facilidade
pelo interpretador. Por outro lado, em geral, o controle que o interpretador tem
sobre o programa que est sendo executado maior, e possvel detectar
durante a execuo situaes de erro invisveis (ou imprevisveis) para o
compilador durante a fase de traduo.

Anlise lxica e sinttica das LPs

Na seo anterior, o leitor deve ter percebido nos grficos que


mostram os processos de compilao pura e de interpretao hbrida a
presena dos analisadores lxico e sinttico, que recebem como entrada o
programa codificado em alguma linguagem de alto nvel, como C, Pascal,
Java e outras.
Para entender este processo, vamos, inicialmente, analisar como o
mesmo feito nas linguagens naturais, como o Portugus. Por exemplo,
podemos escrever a orao ns bacana, onde verificamos um erro de
concordncia porque o verbo no est concordando com o sujeito.
Algo semelhante existe na verificao da corretude de um programa
computacional, onde a linguagem utilizada artificial. Por exemplo, a
instruo em C, if x = 10 y = 12 apresenta alguns erros: o comando if exige
que a expresso booleana de teste seja escrita entre parnteses, o operador
de teste de igualdade simbolizado por == e toda instruo em C termina
com um ponto e vrgula. Isto significa que a instruo correta seria if (x ==
10) y = 12; . A anlise e deteco destes erros o papel dos analisadores
lxico e sinttico, vistos nas figuras da seo anterior.
Anlise lxica e sinttica se refere forma. Existe, no entanto, a
anlise semntica que se relaciona ao significado das instrues. Uma
instruo pode estar sintaticamente correta, mas, semanticamente, errada.
Em Portugus, temos algo semelhante. Por exemplo, podemos escrever
ns comemos o sol. Sintaticamente est correta, mas no apresenta um
significado coerente. Um fenmeno semelhante pode ocorrer nos programas
computacionais, ou seja, uma instruo ou um conjunto delas pode estar
correto sintaticamente e, no entanto, pode no apresentar um significado
coerente. Este o caso de uma anlise semntica e que bem mais

Caractersticas das Linguagens 23


complicada de ser feita pelos compiladores. Resumidamente, os processos
de anlise lxica e sinttica so bem mais fceis de serem realizados pelos
compiladores, que o processo de anlise semntica.
Existem procedimentos formais para a construo de analisadores
sintticos e semnticos, mas, estes ltimos, ainda carecem de muita pesquisa
para serem construdos com facilidade.

A descrio formal de uma LP por BNF

Na dcada de 50, John Backus e Noam Chomsky criaram metodologias


para descrever a sintaxe das linguagens de programao e das linguagens
naturais, respectivamente. Chomsky dividiu as linguagens naturais em quatro
classes de gramticas. Onde, duas delas, as linguagens livres de contexto
e as linguagens regulares, foram utilizadas para descrever a sintaxe das
linguagens de programao.
Peter Naur e John Backus construram uma metodologia para
descrever as linguagens de programao que ficou conhecida como
Backus-Naur-Form, popularmente conhecida como BNF, que se tornou uma
metalinguagem, ou seja, uma linguagem utilizada para descrever outras
linguagens. A BNF foi utilizada pela primeira vez para descrever a sintaxe
da linguagem Algol 58, apresentada por John Backus em uma conferncia
internacional em 1959. At hoje, a BNF a metodologia mais utilizada para
descrever linguagens artificiais.
A BNF usa abstraes para estruturas sintticas. Uma simples
instruo de atribuio em C, por exemplo, poderia ser representada pela
abstrao <atribuio>, onde os colchetes angulados so utilizados para
delimitar abstraes que so conhecidas como no terminais. Uma instruo
de atribuio em C pode ser representado em BNF por:
<atribuio> <var> = <expresso>
Onde, o smbolo esquerda da seta chamado de lado esquerdo,
LE, a abstrao que est sendo definida pelo lado direito. Cada instruo
deste tipo conhecida como regra de produo ou apenas produo.
O analisador lxico divide o programa, um string, em unidades
sintticas chamadas lexemas, que incluem os identificadores, os literais,
os operadores e as palavras especiais da linguagem. Pode-se dizer que
um programa uma sequncia de lexemas, em vez de uma sequncia de
caracteres.

24 unidade 1
Os lexemas so agrupados em determinada categoria formando os
tokens, ou seja, conjuntos de lexemas de uma mesma categoria, podem ser
compostos por apenas um lexema. Por exemplo, a instruo C, cont = 4 *
num + 5; assim analisada:

Lexema Token
cont identificador
= Sinal_de_igualdade
4 Literal_inteiro
* Operador_mult
num identificador
+ Operador_soma
5 Literal_inteiro
; Ponto_e_vrgula

A BNF um dispositivo generativo utilizado para definir linguagens,


onde as sentenas da linguagem so geradas por uma sequncia de
aplicaes das regras, iniciando por um smbolo inicial. Para a BNF, os tokens
so conhecidos como smbolos no terminais e os lexemas so smbolos
terminais. Os smbolos terminais s podem aparecer do lado direito da
produo, enquanto os no terminais podem aparecer dos dois lados.
Exemplo 1.1. Seja a seguinte gramtica:
<atrib> <id> = <expr>
<id> A | B | C
<expr> <expr> + <termo>
| <termo>
<termo> <termo> * <fator>
| <fator>
<fator> ( <expr> )
| <id>
Verifiquemos que a sentena A = B * (C + D) pertence linguagem
definida por esta gramtica.
<atrib> <id> = <expr>
A = <expr>
A = <termo>
A = <termo> * <fator>
A = <fator> * <fator>
A = <id> * <fator>

Caractersticas das Linguagens 25


A = B * <fator>
A = B * (<expr>)
A = B * (<expr> + <termo>)
A = B * (<termo> + <termo>)
A = B * (<fator> + <termo>)
A = B * (<id> + <termo>)
A = B * (C + <termo>)
A = B * (C + <fator>)
A = B * (C + <id>)
A = B * (C + D)

Desta forma, a sentena pode ser derivada a partir da gramtica, ou


seja, uma sentena da linguagem definida pela gramtica.
O sistema de derivao anterior pode ser mostrado, graficamente,
atravs de uma rvore, chamada de rvore de anlise ou parse tree,
onde os ns internos representam os no terminais, e as folhas da rvore
representam terminais. Para o Exemplo anterior, a parse tree correspondente
sentena A = B * (C + D) est mostrada na Figura 1.7. Na figura, pode-se
verificar a sentena observando as folhas da rvore.

Figura 1.7 Parse tree para A = B * (C + D).

26 unidade 1
Algumas observaes podem ser feitas sobre a parse tree. Inicialmente,
muitas propriedades da gramtica podem ser observadas diretamente na
rvore. Por exemplo, verifica-se que a operao + da sentena aparece
na rvore em um nvel mais baixo que o do operador *. Ao se implementar
esta rvore, o processo deve ser iniciado pelas folhas, portanto, o operador
que est mais abaixo na rvore vai ser implementado primeiro. Isto significa
que este operador tem precedncia sobre o anterior. De outra forma, a rvore
mostra qual a ordem de precedncia entre os operadores da gramtica.
Outra observao que pode ser feita diretamente da parse tree que,
se a rvore se expande pela direita ou pela esquerda, isto significa, que, a
associatividade das operaes feita pela direita ou pela esquerda.
A parse tree nica para as gramticas no ambguas, ou seja, para
cada sentena de uma gramtica no ambgua, existe apenas uma parse tree
associdada a ela se a gramtica for no ambgua.

Paradigmas das linguagens de programao

As linguagens de programao so classificadas em paradigmas,


algumas vezes chamados de modelos. Estes paradigmas so:
o paradigma imperativo;
o paradigma funcional;
o paradigma lgico e
o paradigma orientado a objetos.

Essa classificao no representa a unanimidade de pontos de vistas


dos projetistas e pesquisadores das linguagens de programao. Sendo
alegado, por alguns, que o paradigma orientado a objetos nada mais que
uma particularizao do paradigma imperativo, muitos advogando a existncia
do paradigma concorrente, dado o advento das arquiteturas paralelas e a
necessidade destas linguagens para permitir a programao de softwares
para estas mquinas.

O paradigma imperativo

A grande maioria das linguagens obedece ao paradigma imperativo,


sendo este, o modelo ao qual faremos referncia neste estudo.
O modelo Imperativo baseado na perspectiva do computador,

Caractersticas das Linguagens 27


onde a execuo sequencial de comandos e o uso de dados so conceitos
baseados no modo como os computadores executam programas, no nvel de
linguagem de mquina. Este modelo o predominante. As LPs imperativas
so de fcil traduo. Um programa imperativo equivalente a uma sequncia
de modificaes de locaes de memria.
Exemplos de linguagens Imperativas so: FORTRAN, COBOL,
ALGOL 60, APL, BASIC, PL/I, SIMULA 67, ALGOL 68, PASCAL, C, MODULA
2, ADA, alm de outras.

O paradigma funcional

O paradigma funcional apresenta uma metodologia diferente da


imperativa, sendo baseada inteiramente em funes matemticas, a sua
base de projeto. Em uma programao funcional pura no existem atribuies
destrutivas, ou seja, se for atribudo um valor a uma varivel x, em algum
ponto do programa, nenhum outro valor poder ser atribudo mais a x, neste
programa. Nos programas funcionais, as variveis mais se parecem com
constantes. Isto implica que programas no apresentam quaisquer efeitos
colaterais. Os programas funcionais so altamente modulares e representam
uma escolha importante para a execuo paralela de programas. At certo
tempo atrs, as linguagens funcionais foram deixadas em um segundo plano,
em parte, devido a algumas dificuldades que elas apresentavam em relao
computao com arquivos e entrada e sada. No entanto, este panorama
tem se modificado com o surgimento de novas pesquisas e tecnologias,
observando-se um aumento cada vez maior de sistemas codificados em
linguagens funcionais, onde a sua forte fundamentao matemtica torna
estes programas bem mais fceis de serem provadas as suas corretudes. H
de ser salientado que, um programa funcional tem, em mdia, um quinto do
tamanho de um programa imperativo para resolver o mesmo problema. Em
muitos casos, este valor chega a 1/20 avos. Alm disso, muitas bibliotecas e
ferramentas de ajuda ao desenvolvimento de sistemas tm sido projetadas.
Exemplos dessas linguagens podem ser Lisp, SML, Miranda, KRC,
Erlang e Haskell, onde muitos sistemas tm sido codificados e em diversas
reas de aplicao.

28 unidade 1
O paradigma lgico

O paradigma lgico utiliza a Lgica simblica como fundamento para


sua programao, notadamente a Lgica de Predicados de 1 ordem, portanto,
muito diferente das linguagens imperativas e das funcionais. Para atingir
seus objetivos, a programao lgica utiliza de regras de inferncias e as
clusulas de Horn, alm da teoria dos quantificadores universal e existencial
da Lgica de Predicados. Este paradigma ainda no tem apresentado
uma grande opo por parte dos programadores, principalmente, devido
ao desempenho apresentado com o atual estgio de desenvolvimento do
hardware e a dificuldade de se programar neste paradigma. Atualmente, a
nica linguagem que tem representado este paradigma tem sido Prolog.

O paradigma orientado a objetos

O modelo Orientado a Objeto focaliza mais o problema. Um programa


OO equivalente a objetos que mandam mensagens entre si. Os objetos do
programa equivalem aos objetos da vida real (problema). A abordagem OO
importante para resolver muitos tipos de problemas atravs de simulao.
A primeira linguagem OO foi Simulada, desenvolvida em 1966 e
depois refinada em Smalltalk. Existem algumas linguagens hbridas: Modelo
Imperativo mais caractersticas de Orientao a Objetos (OO). Ex: C++.
No modelo OO a entidade fundamental o objeto. Objetos trocam
mensagens entre si e os problemas so resolvidos por objetos enviando
mensagens uns aos outros.
Os componentes bsicos de uma linguagem orientada a objetos so
os seguintes:
Objetos: um objeto um conjunto encapsulado de operaes
e um estado que registra e lembra o efeito das operaes. Um
objeto executa uma operao em resposta ao recebimento
de mensagem que est associada operao. O resultado da
operao depende do contedo da mensagem recebida e do
estado do objeto, quando ele recebe a mensagem. O objeto
pode, como parte dessa operao, enviar mensagem para outros
objetos e para si mesmo.
Mensagens: so requisies enviadas de um objeto a outro,
para que este produza algum resultado desejado. A natureza das

Caractersticas das Linguagens 29


operaes determinada pelo objeto receptor. Mensagens podem
ser acompanhadas de parmetros, que so aceitos pelo objeto
receptor e que podem ter algum efeito nas operaes realizadas.
Esses parmetros so eles prprios, objetos.
Mtodos: so descries de operaes que um objeto realiza
quando recebe uma mensagem. Uma mesma mensagem poderia
resultar em mtodos diferentes, quando enviada para diferentes
objetos. O mtodo associado com a mensagem pr-definido.
Um mtodo similar a um procedimento; mas h diferenas.
Classes: uma classe um template para objetos. Consiste de
mtodos e descries de estado que todos os objetos da classe
iro possuir. Uma classe similar a um TAD, no sentido de que
ela define uma estrutura interna e um conjunto de operaes que
todos os objetos, que so instncias da classe, possuiro. Uma
classe tambm um objeto, e, portanto, aceita mensagens e
possui mtodos e um estado interno. Uma mensagem que muitas
classes aceitam uma mensagem de instanciao, que institui a
classe a criar um objeto que um elemento ou instncia da classe
receptora.

O paradigma orientado a objeto para ser operacional tem de


apresentar as seguintes propriedades:

Encapsulamento: cada objeto visto como o encapsulamento de


seu estado interno, suas mensagens, e seus mtodos. A estrutura
do estado e os pares mensagem-mtodo so todos definidos
pela classe qual o objeto pertence. O valor do estado interno
determinado pelos mtodos que o objeto executa em resposta s
mensagens recebidas.
Polimorfismo: a propriedade que permite que uma mesma
mensagem seja enviada a diferentes objetos, sendo que cada
objeto executa a operao apropriada sua classe. Mais
importante: o objeto que envia a mensagem no precisa conhecer
a classe do objeto receptor ou como aquele objeto ir responder
mensagem. Isto significa que a mensagem, por exemplo, print
pode ser enviada a um objeto, sem a preocupao se aquele
objeto um caracter, um inteiro, uma string ou uma figura. O

30 unidade 1
objeto receptor ir responder com o mtodo que for apropriado
sua classe.
Herana: uma das propriedades mais importantes do modelo
OO. Ela possvel via definio de hierarquia de classes, isto ,
uma estrutura em rvore de classes, onde cada classe tem 0 ou
mais subclasses. Uma subclasse herda todos os componentes
de sua classe-pai, incluindo a estrutura do estado interno e
pares mtodo-mensagem. Toda propriedade herdada pode ser
redefinida na subclasse, sobrepondo-se definio herdada.
Esta propriedade encoraja a definio de novas classes, sem
duplicao de cdigo.

Exerccio

1. Qual a utilidade do conhecimento sobre as linguagens de programao?

2. Que linguagem de programao dominou a computao cientfica ao longo


dos anos?

3. Que linguagem de programao dominou a computao comercial ao


longo dos anos?

4. Que linguagem de programao dominou a inteligncia artificial ao longo


dos anos?

5. O que significam legibilidade, redigibilidade e ortogonalidade, no contexto


de caractersticas de linguagens de programao?

6. Quais foram as duas deficincias das linguagens de programao


descobertas em consequncia da pesquisa em desenvolvimento de software
da dcada de 70?
7. Quais as diferenas existentes entre os programas interpretados e
compilados?

8. O que significa interpretao hbrida no contexto de implementao de


linguagens?

Caractersticas das Linguagens 31


9. Quais os paradigmas das linguagens de programao e que reas cada
um se destaca?

Exerccio. Usando a gramtica do Exemplo 1.1 mostre uma rvore de


anlise e uma derivao das seguintes instrues:
a) A = (A + B) * C
b) A = B + C + A
c) A = A + (B * C)
d) A = B * (C * (A + B))

SAIBA MAIS

O material mostrado nesta unidade foi, em grande parte, retirado do


livro do Robert Sebesta, que consideramos uma excelente referncia neste
assunto. As anotaes de aula do Professor Jos Lucas M. Rangel Netto, da
Puc-Rio, tambm apresentam um material de boa qualidade. No entanto,
muito outras referncias sobre este tema existem e podem ser consultadas
pelo leitor, at porque, este um tema recorrente para os profissionais da
rea da Informtica e da Computao.

32 unidade 1
UNIDADE 2
Variveis e Tipos de Dados

Resumindo
O objetivo principal desta Unidade conhecer com profundidade conceitos inerentes s variveis
e aos tipos de dados. Os conceitos e propriedades referentes a estes temas so importantes
para entender o comportamento de programas. As variveis e seus atributos decidem uma parte
importante da computao e os tipos de dados so importantes na verificao da corretude
dos tipos e das operaes que estes tipos podem realizar com os valores das variveis. Outra
parte importante dos sistemas computacionais diz respeito ao gerenciamento da memria em
tempo de execuo. Este gerenciamento deve ser feito de forma automtica pelo sistema em vez
de ser realizado pelo programador que pode cometer algum erro ao esquecer uma desalocao
necessria. As clulas que no so mais referenciadas em um programa devem ser incorporadas ao
rol de clulas livres para que possam ser reutilizadas e compartilhadas. A forma de apresentao
utilizada de acordo com o exigido para o ensino a distncia, ou seja, tendo em vista sempre esta
nova modalidade de ensino.
variveis e tipos de dados

Introduo

As linguagens de programao imperativas


representam, em um nvel mais abstrato, a
arquitetura de von Neumann, onde a memria e o
processador so os elementos bsicos. A memria
porque onde so armazenadas as instrues de
um programa em linguagem de mquina e tambm
os dados necessrios para a execuo de um
programa. Neste sentido, as clulas de memria
so representadas pelas variveis em um nvel
mais alto e, portanto, mais abstrato. Por exemplo,
uma varivel cont do tipo inteiro em um programa
C, representa, em um nvel mais abstrato, uma
clula de memria composta de 32 ou 64 bits.
Em um nvel mais baixo, temos uma clula de 32
ou 64 bits, e uma representao desta clula em
um nvel mais abstrato a varivel que tem um
nome identificador que cont. Na realidade, o nome apenas um dos vrios
atributos que as variveis tm, uma vez que outros tambm existem e so
objetos de estudo nesta unidade.
Entre os atributos que as variveis tm, um se destaca, que o tipo
da varivel. Dizer que uma varivel de um determinado tipo, significa que
se est informando quais os possveis valores que ela pode assumir e quais
operaes podem ser realizadas sobre os valores deste tipo, ou seja, com
aquela varivel. Deve ser notado que esta mesma observao se aplica, de
forma idntica, aos conjuntos matemticos.

Varives e Tipos de Dados 35


Atributos de uma varivel

J foi observado que as variveis apresentam algumas propriedades


e caractersticas que so chamadas de atributos. So 6 (seis) os atributos
principais das variveis: o nome, o valor, o tipo, o endereo, o escopo e o
tempo de vida. Estes atributos podem ser observados na figura a seguir.
Na figura aparece, em cor escura, uma
outra entidade que a vinculao (binding). Na
realidade, a vinculao uma associao entre
um atributo e a varivel, devendo ser destacado o
momento em que esta associao realizada, ou
seja, o momento em que acontece o casamento
entre a varivel e cada atributo. Estes tempos
podem ser: no tempo de projeto da linguagem,
no tempo de implementao da linguagem, no
tempo de compilao do programa, no tempo
de carregamento do programa ou no tempo
de execuo do programa. Estes tempos so
conhecidos como tempo de vinculao (binding
time) e podem ter influncia sobre o resultado da
execuo dos programas. Uma vinculao esttica se ocorrer antes do
tempo de execuo, normalmente, em tempo de compilao, e permanecer
inalterada ao longo da execuo do programa. Se ela ocorrer durante a
execuo ou puder ser alterada, conhecida como dinmica.

O nome das variveis.

Os nomes so utilizados para identificar variveis, procedimentos,


funes e palavras especiais da linguagem. As primeiras linguagens
de programao s admitiam nomes de identificadores com apenas um
caractere, a exemplo das variveis utilizadas na Matemtica. O Fortran
I e Fortran 77 permitem que os nomes de identificadores tenham at 6
caracteres. O Fortran 90 e C permitem at 31 caracteres, enquanto Ada e
Java permitem nomes com qualquer quantidade de caracteres e todos so
significativos. C++ nada define sobre este fato. Algumas linguagens fazem
diferena entre letras maisculas e minsculas. Esta deciso s atrapalha a
redigibilidade dos programas. o caso de C, Java e C++, enquanto Pascal

36 unidade 2
no faz esta diferena. As palavras especiais podem ser palavras-chave se
forem especiais em apenas alguns contextos, como o caso do printf de
C que s tem significado prprio se o arquivo stdIO.h estiver includo no
programa. Se uma palavra especial s puder ser utilizada para a finalidade
para a qual foi definida, dizemos que a palavra reservada.

O endereo das variveis.

O endereo de uma varivel o mesmo endereo da clula na


memria do computador. Uma observao sobre os endereos que uma
mesma varivel pode ser associada a mais de um endereo em um programa,
desde que em tempos diferentes. Por exemplo, dois subprogramas podem
declarar localmente uma varivel com o mesmo nome, por exemplo, cont.
Como os subprogramas so independentes, as referncias a cont podem
acontecer sem qualquer conflito. Por outro lado, o mesmo endereo pode
ser referenciado por mais de uma varivel. Neste caso, dizemos que estas
variveis com o mesmo endereo so apelidos. Os apelidos podem trazer
complicaes para o programa. Por exemplo, o valor de um dos apelidos
pode ser modificado sem que outro apelido tenha conhecimento disto.
Normalmente, estes casos acontecem com ponteiros, mas podem ocorrer,
tambm, em vetores ou com registros variantes de Pascal e Ada ou com as
unions de C e C++.

Os valores das variveis

O valor de uma varivel o contedo das clulas de memria


associadas a ela. Por exemplo, para as variveis inteiras so reservadas
clulas do tamanho da palavra do computador. Em um computador em
que a palavra seja de 64 bits, por exemplo, a arquitetura IA64 da Intel,
para as variveis do tipo inteiro so reservadas clulas de memria de 64
bits. Normalmente, estas mquinas utilizam aritmtica complementar de 2
para estes valores, onde o primeiro bit, o da extrema esquerda da clula,
representa o bit de sinal, sobrando 63 bits para representar os valores das
variveis inteiras, ou seja, valores entre -231 a 231-1. Para valores de outros
tipos, as representaes so evidentemente distintas.

Varives e Tipos de Dados 37


Os escopos das variveis

Antes de analisar a ideia de escopo, necessrio introduzir a ideia


de blocos nas linguagens de programao. Esta metodologia foi introduzida
na linguagem ALGOL 60 e permite que uma seo de cdigo tenha suas
prprias variveis locais. Um bloco um construtor de programa que delimita
o escopo de qualquer declarao dentro dele. As variveis declaradas em um
bloco so associadas ao armazenamento no instante em que a execuo do
programa atinge o incio do bloco, e so desfeitas, quando o bloco termina
de ser executado.
Um bloco , essencialmente, formado por uma sequncia de
declaraes (declaraes de procedimento e variveis locais ao bloco),
seguida de uma sequncia de comandos, e , normalmente, identificado pela
presena de palavras reservadas ou por smbolos de incio e fim de bloco,
como os pares Begin e end ou { e }.

begin
<declaraes>
<comandos>
end.

Um programa Algol um bloco; funes e procedimentos (que


correspondem s funes e sub-rotinas de FORTRAN) so blocos declarados
pelo acrscimo de um cabealho a um bloco bsico (begin ... end). A diferena
entre uma funo e um procedimento o fato de que uma funo devolve
(retorna) um valor, mas, o que dito a respeito de procedimentos se aplica
tambm a funes.
Um bloco annimo, isto , um bloco sem cabealho, pode ser usado
como um comando qualquer, e entendido como um procedimento sem
...
nome e sem parmetros.
If (x > y) {
Int z = x; Vejamos o exemplo ao lado em Java. Neste bloco, sem nome, a
x = y; varivel inteira z declarada, sendo visvel apenas dentro deste bloco que
y = z; o seu escopo. Este tipo de bloco substitui um comando e, por este motivo, ele
};
conhecido como um comando em bloco.
...
possvel tambm uma expresso em bloco que uma forma de
expresso que contm uma declarao local (ou um grupo de declaraes) D
e uma subexpresso E. As vinculaes produzidas por D so usadas apenas
para avaliar E.

38 unidade 2
Nas linguagens C, C++ e Ada, o corpo de uma funo uma expresso
em bloco.

Exemplo 2.1. Suponha, na


Em Haskell:
figura ao lado, que as variveis x,
area x y z = let s = (x + y + z) / 2.0
y e z representem as medidas dos
in sqrt (s * (s x) * (s y) * (s z))
lados de um tringulo qualquer. As Em C++:
expresses em bloco, em Haskell float area (float x, y, z) {
e em C++, calculam as reas de float s = (x + y + z) / 2.0;
quaisquer tringulos. A chamada return sqrt (s * (s x) * (s y) * (s z));
em Haskell ser area x y z. Em }
C++, ser area (x, y, z);

Algumas linguagens, no entanto, s admitem blocos com um nome


identificador. Este o caso de Pascal, que s admite blocos com identificadores
na forma de funo (function) ou de um procedimento (procedure).

As regras de escopo

Em um programa, o escopo de uma varivel a faixa deste programa


em que a varivel visvel. Dito de outra forma, a faixa do programa onde
a varivel pode ser referenciada.
Uma varivel declarada dentro de um bloco dita local a este bloco.
Se ela for declarada fora de qualquer bloco, ela dita global. As variveis
globais so visveis em qualquer parte do programa. Pode ser que uma varivel
no seja local nem seja global. Isto pode acontecer se a linguagem admite
escopos aninhados, como o caso de Pascal, Mdula e Ada, e for feita uma
referncia a uma varivel cuja declarao foi feita em um bloco entre o bloco
onde a referncia feita e o bloco mais externo que o programa. Neste
caso, dizemos que a varivel no local ao bloco onde ela referenciada. A
varivel referenciada tem de estar em bloco a ser determinado e isso depende
de que tipo de escopo utilizado pela linguagem, ou seja, se ela usa escopo
esttico ou escopo dinmico.

Escopo esttico

O escopo esttico recebeu este nome porque ele pode ser determinado

Varives e Tipos de Dados 39


estaticamente, ou seja, antes da execuo. Neste caso, quando uma varivel
referenciada, verifica-se se existe uma declarao dela no bloco. Se existir,
ela ser local e tem os atributos ali declarados. Se no existir tal declarao,
ela uma varivel no local e a sua declarao deve estar em um bloco na
cadeia de blocos aninhados. O bloco que tem um bloco declarado dentro dele
o pai esttico. Pode ser que exista um av esttico, um bisav, etc., que
sero, genericamente, chamados de ancestrais estticos. O conjunto de
ancestrais estticos define a cadeia esttica.
Existe tambm escopo dinmico que ser visto mais adiante ainda
nesta seo. No entanto, verifica-se que os programas escritos em linguagens
que utilizam regras de escopo esttico, apresentam desempenhos melhores
que os programas codificados em linguagens que utilizam regras de escopo
dinmico. No entanto, existem muitas linguagens com escopo dinmico
devido flexibilidade que estas linguagens proporcionam. Os motivos destes
fatos sero esclarecidos mais adiante neste trabalho.
Vejamos a seguir alguns exemplos que mostram a aplicao destas
regras.

Procedure big; Exemplo 2.2. O fragmento de


Var x : Integer; programa ao lado mostra um exemplo
Procedure sub1; de encadeamento esttico em Pascal.
Begin { sub1 } Neste caso, quando a varivel x
. . . . x . . . {------ ponto 1 -------} referenciada, verifica-se a existncia
End; {su1} de uma declarao para ela dentro
Procedure sub2;
de sub1. Como esta declarao no
Var x : Integer;
existe, feita uma busca no pai esttico
Begin { sub2 }
do procedimento onde ela citada,
....
End; { sub2 } ou seja, o pai esttico de sub1 que
Begin {big } o procedimento big, onde sub1 foi
....... declarado. Em big existe uma declarao
End. {big} para x; portanto, esta a sua referncia.

preciso salientar que, em uma linguagem que utiliza regras de


escopo esttico, possvel que exista mais de uma declarao para a mesma
varivel em blocos aninhados. Neste caso, a declarao de uma varivel em
um bloco mais interno esconde as referncias feitas a esta mesma varivel,

40 unidade 2
mas que esteja em um bloco mais externo. As linguagens que adotam esta
metodologia devem prover formas de acesso s variveis ocultas mais
externas. Em C e em C++, o operador de escopo :: utilizado para esta
funo. Se uma varivel global x estiver oculta por uma declarao local
de x, a varivel global pode ser referenciada atravs da declarao ::x.
Vamos verificar, a seguir, um exemplo que mostra o processo de ocultao
de variveis em uma linguagem simples, como Pascal.

Exemplo 2.3. Vejamos


Program main;
o exemplo ao lado, tambm Var x : Integer;
em Pascal, onde a varivel x, Procedure sub1;
referenciada dentro de sub1, Var x : Integer;
no ponto 1 do programa, local Begin { sub1 }
e esconde a declarao de x . . . x . . . . {-----ponto 1 -----}

dentro do programa main. Se End; {sub1 }


Begin { main }
for necessrio referenciar o x
.....
declarado em main, no ponto 1,
End. { main }
deve-se usar main.x.

Escopo dinmico

Alm do escopo esttico, existe tambm o escopo dinmico que


adotado por algumas linguagens. Entre elas podemos citar APL, SNOBOL,
Perl, PHP e Python, alm de outras. Devemos nos lembrar que, no escopo
esttico, um subprograma tem seu pai esttico que o subprograma onde ele
foi declarado. J no escopo dinmico, um subprograma tem seu pai dinmico
que o subprograma que fez a chamada ao subprograma ou bloco, durante
a execuo do programa. Isto significa que no escopo esttico importante
saber onde um subprograma ou bloco foi declarado e no escopo dinmico
importante saber qual foi o subprograma ou bloco que fez a chamada ao
subprograma ou bloco.
O bloco ou subprograma chamador referenciado como pai dinmico,
e, o processo de busca por uma varivel no local se d atravs da cadeia
dinmica, ou seja, seguindo a sequncia de chamadas dos procedimentos.
Neste caso, necessrio que o programa tenha registrado em algum lugar
esta sequncia de chamadas.

Varives e Tipos de Dados 41


Para entender melhor esta metodologia, vamos reanalisar o mesmo
exemplo mostrado anteriormente, agora luz das regras de escopo dinmico.

Exemplo 2.4. Seja o


Procedure big;
programa ao lado, o mesmo do
Var x : Integer;
Procedure sub1; Exemplo 2.2. Supondo que a
Begin { sub1 } linguagem usa agora escopo
. . . . x . . . {------ ponto 1 -------} dinmico. Vamos imaginar que
End; {su1} a sequncia de chamadas seja
Procedure sub2; esta: big chama sub2 que chama
Var x : Integer; sub1.
Begin { sub2 }
Neste caso, a varivel x,
....
no ponto 1, a declarada em sub2.
End; { sub2 }
Se a sequncia de chamadas
Begin {big }
....... fosse big que chama sub1, a
End. {big} varivel x seria a declarada em
sub1.

A utilizao de escopo dinmico tem recebido algumas crticas dos


pesquisadores. A primeira delas refere-se ao fato de que, durante a execuo
de um bloco ou subprograma, todas as variveis locais a este bloco so
visveis a qualquer outro bloco ou subprograma em execuo. E, no existe
qualquer forma de proteger as variveis locais dessa acessibilidade, tornando
os programas dinmicos, menos confiveis que os estticos.
Um segundo problema com o escopo dinmico se refere incapacidade
de se verificar, estaticamente, os tipos das referncias.
Outro problema com o escopo dinmico que ele torna muito difcil a
leitura dos programas, porque a sequncia de chamadas deve ser conhecida
para se determinar o significado das referncias a variveis no locais.
Finalmente, os acessos a variveis no locais em linguagens com
escopo dinmico levam mais tempo que em linguagens com escopo esttico.

Os tempos de vida das variveis

As variveis so criadas ou alocadas em algum instante de tempo


bem definido e so destrudas ou desalocadas em algum tempo depois,
quando no forem mais necessrias. O intervalo de tempo ocorrido entre a

42 unidade 2
criao e a destruio de uma varivel conhecido como o seu tempo de vida.
Uma varivel s deve estar associada ao seu armazenamento, ocupando
memria, durante o seu tempo de vida. Quando uma varivel destruda
ou desalocada, a rea de memria ocupada por ela pode ser alocada para
outros propsitos. Isto significa economia de memria. As variveis podem
ser classificadas de acordo com os seus tempos de vida:

O tempo de vida de uma varivel global o tempo em que o


programa esteja em execuo.
O tempo de vida de uma varivel local o tempo de ativao do
bloco em que ela foi declarada.
O tempo de vida de uma varivel heap arbitrrio, mas limitado
ao tempo de execuo do programa.
O tempo de vida de uma varivel persistente (uma varivel arquivo)
arbitrrio e pode transcender a execuo de um programa.

Exemplo 2.5. Considere o programa em C ou C++; mostrado na


figura a seguir. Ao lado direito mostrado um grfico com os tempos de vida
de cada uma das variveis declaradas no programa. No grfico, a abreviao
TV significa tempo de vida.

Varives e Tipos de Dados 43


Classificao das variveis

As variveis podem ser classificadas em escalares (no estruturadas),


por exemplo, byte, word, inteiras, reais e booleanas; e estruturadas, se forem
construdas a partir de outras, estruturadas ou no. As variveis escalares
podem ser classificadas em quatro tipos, de acordo com os seus tempos de
vida.

Variveis estticas

As variveis estticas so vinculadas a clulas de memria antes de o


programa iniciar sua execuo, permanecendo assim, at o final da execuo.
Isto permite que seja utilizado o endereamento direto, que muito mais
rpido que outros tipos de endereamento. Alm disso, pode ser necessrio
que uma varivel local mantenha o valor anterior em uma chamada. Diz-se
que esta varivel deve ser sensvel histria.
No entanto, este tipo de varivel tem desvantagens. Por exemplo,
se um subprograma tiver variveis estticas ele no pode ser recursivo. No
Fortran I, II e IV todas as variveis eram estticas. Em C, C++ e em Java,
a linguagem permite que o programador utilize o especificador static na
declarao de uma varivel que mantm o valor entre as chamadas.

Variveis dinmicas na pilha

As variveis dinmicas na pilha tm os seus tipos associados


estaticamente, mas elas s so associadas a um armazenamento quando
o bloco em que elas so declaradas iniciar a sua execuo, e acaba esta
vinculao quando o bloco acaba a sua execuo. Este tipo de varivel em
um subprograma permite que ele seja recursivo. Esta denominao devida
ao fato de que a execuo dos subprogramas realizada com os registros
de ativao, que so instncias dos subprogramas, e so colocadas em uma
estrutura de pilha conhecida como a pilha do sistema. Este tipo de varivel
permite que a rea de pilha seja reutilizada para outras finalidades, permitindo
compartilhamento de memria.

44 unidade 2
Variveis dinmicas no heap explcitas

As variveis dinmicas no heap (tambm conhecido como monte)


explcitas so clulas sem nomes e que se localizam em uma rea da memria
principal, onde o acesso a variveis nesta rea s permitido atravs de
variveis do tipo ponteiro. A heap uma rea de memria caracterizada pela
grande desorganizao, porque ali as clulas so alocadas e desalocadas,
explicitamente, mas sem qualquer ordem. Vejamos o exemplo a seguir em C,
onde pode-se ver esta situao.

Exemplo 2.6. Este


exemplo mostra um trecho de
programa em C, mostrando
o cdigo do lado esquerdo
e uma figura do lado direito
representando o heap durante
a execuo do programa. A
varivel ponteiro ptr alocada
na rea para as variveis
escalares que so dinmicas
na pilha, e o resultado da chamada a malloc a alocao de uma rea para
a varivel do tipo struct livro, retornando um ponteiro (endereo) para esta
rea que ser o valor atribudo a ptr.

Variveis dinmicas no heap implcitas

As variveis no heap implcitas so vinculadas ao armazenamento


no heap somente quando so atribudos valores a elas, que tambm o
instante da vinculao de todos os atributos da varivel. Essas variveis
podem ter atributos distintos em cada valor a elas atribudo. Variveis deste
tipo tm o maior grau de flexibilidade, permitindo que se escreva um cdigo
altamente genrico. Uma grande desvantagem das linguagens que utilizam
este tipo de varivel a sobrecarga necessria para manter a contabilidade
destes atributos atualizada, toda vez que um novo valor atribudo a uma
varivel, alm de tornar impossvel a deteco de erros pelo compilador. Por
este motivo, poucas linguagens utilizam esta tcnica. Perl, APL, JavaScript,
Python e PHP so exemplos destas linguagens.

Varives e Tipos de Dados 45


Tipos de dados

Apesar dos tipos de dados serem um dos atributos de uma varivel,


conforme foi visto na seo anterior, eles tm uma importncia vital para a
computao e, por este motivo, sero analisados de forma particular, sendo
dedicada esta seo a este estudo.
Ao se declarar uma varivel como sendo de um determinado tipo,
na realidade se est dando duas informaes importantes. A primeira delas
se refere aos possveis valores que esta varivel pode assumir. A segunda
informao diz respeito a quais operaes podem ser aplicadas a todos os
valores do tipo. Assim, existe uma correspondncia entre os tipos e alguns
tipos de conjuntos. A existncia desta correspondncia nos permite afirmar,
de maneira informal, que os tipos de dados na Computao correspondem
exatamente a alguns conjuntos na Matemtica.
No entanto, nem todo conjunto corresponde a um tipo. necessrio
que as operaes entre os elementos do conjunto possam ser aplicadas
a todos os elementos desse conjunto. Por exemplo, o conjunto {13, true,
Jos} no representa um tipo, porque no existe qualquer operao que
possa ser aplicada a todos os elementos desse conjunto. Desta forma, os
tipos de dados podem ser identificados como, conjuntos matemticos, e isto
ser feito neste estudo, uma vez que, a teoria matemtica dos conjuntos j
bastante conhecida e desenvolvida. Esta tcnica adequada para este
estudo, apesar da teoria dos conjuntos ser incompleta.
Os tipos de dados so classificados em tipos primitivos e tipos
compostos.

Tipos de dados primitivos

Um tipo de dado primitivo se seus valores no podem ser decompostos


em tipos mais simples. Estes tipos podem ser os tipos numricos (inteiros e
reais), o tipo booleano e o tipo caractere.
Todas as linguagens de programao proveem tipos de dados
primitivos pr-definidos, mas somente algumas delas permitem que o
programador possa definir um novo tipo primitivo.

Tipos de dados primitivos pr-definidos pela linguagem

46 unidade 2
Toda linguagem de programao oferece ao programador alguns tipos
pr-definidos que do uma indicao da rea de melhor e maior aplicabilidade
da linguagem, sendo este um bom critrio de anlise de uma linguagem.
Por exemplo, uma linguagem destinada a ser utilizada na rea comercial,
como COBOL, deve apresentar tipos primitivos cujos valores sejam strings
de tamanho fixo e valores de ponto fixo. Uma linguagem destinada a ser
utilizada em computao numrica, como Fortran, deve apresentar tipos
cujos valores sejam nmeros reais e tipos para valores complexos.
No entanto, alguns tipos de dados primitivos so oferecidos por muitas
linguagens, mesmo com nomes distintos. Por exemplo, Java tem boolean,
char, int e float. Ada tem os tipos Boolean, Character, Integer e Float. Os
valores destes tipos so:

Bool = {false, true}


Char = { ..., a, .... z, ..., 0, .... 9, ..., ?, ...}
Integer = { ,...,-2, -1, 0, 1, 2, ....}
Float = { ..., -1.0, ..., 0.0, ..., 1.0, ...}

Os tipos Char, Integer e Float, normalmente, so definidos por


implementao, ou seja, o conjunto de valores determinado pelo compilador.
Algumas vezes estes tipos so definidos pela linguagem, ou seja, o conjunto
de valores definido pela linguagem. Por exemplo, Java define precisamente
todos os seus tipos.
A cardinalidade de um tipo T, escrita como #T, a quantidade de
valores distintos em T, em particular:
#Bool = 2.
#Char = 256 (Cdigo ASCII) ou 65536 (Cdigo Unicode).

Tipos de dados primitivos definidos pelo usurio

Para evitar problemas de portabilidade, algumas linguagens permitem


que o programador defina seus prprios tipos inteiros e pontos flutuantes. Por
exemplo, em Ada, o programador pode estabelecer o intervalo e a preciso
de cada tipo. Por exemplo, vejamos o bloco de programa em Ada, a seguir:
type Populacao is range 0 . . 1e10;
pop_paiz : Populacao;
pop_mundo : Populacao;

Varives e Tipos de Dados 47


Neste caso, as variveis do tipo Populacao podem assumir valores
entre 0 e 1010.
Em algumas linguagens de programao, possvel definir um novo
tipo primitivo inteiro, atravs da enumerao de seus valores. Isto feito
pelos identificadores que denotam os valores. Este tipo conhecido como
enumerao e seus valores so conhecidos como enumerandos. Este o
caso da linguagem Ada.
As linguagens C e C++ tambm suportam enumeraes, mas, nestas
linguagens, as enumeraes so do tipo inteiro, ou seja, cada valor representa
um valor inteiro.
Por outro lado, muitas linguagens apresentam um tipo de dado
primitivo discreto.
Um tipo de dado primitivo discreto aquele cujos valores tm uma
correspondncia biunvoca com um subconjunto dos inteiros.

Tipos de dados compostos

Um tipo composto aquele cujos valores so compostos a partir


de outros valores mais simples. As linguagens de programao suportam
uma grande variedade de tipos compostos ou estruturados como, tuplas,
estruturas, registros, arrays, tipos algbricos, unies discriminadas, objetos,
unies, strings, listas, rvores, arquivos sequenciais, arquivos diretos e
relaes em bancos de dados relacionais. No entanto, todos estes tipos
podem ser analisados e entendidos como funes dos seguintes tipos:
Produtos cartesianos (tuplas, estruturas e registros).
Mapeamentos (arrays).
Unies disjuntas (tipos algbricos, unies discriminadas e
objetos).
Tipos recursivos (listas e rvores).

O tipo produto cartesiano

O produto cartesiano representado pelas tuplas, pelos registros e


pelas estruturas de algumas linguagens.
Utilizamos a notao (x, y) para representar um par onde x a
primeira componente e y a segunda. Utilizamos tambm a notao S x T
para representar o produto cartesiano de S por T que o conjunto dos pares

48 unidade 2
(x, y), sendo x escolhido em S e y escolhido em T. Formalmente, temos:
S x T = {(x, y) | x S y T}
A cardinalidade de S x T dada por:
#(S x T) = #S x #T
A notao para o produto cartesiano de dois conjuntos pode ser
estendida para representar o produto cartesiano de vrios conjuntos. Neste
caso, denotamos por S1 x S2 x ...x Sn cujos valores so as n-uplas onde a
primeira componente est em S1, a segunda em S2, etc. Sendo todos os
conjuntos Si do mesmo tipo, a notao anterior se torna Sn = S x S x ...x S.
Neste caso, a cardinalidade dada por #(Sn) = (#S)n. Considerando o caso
particular em que n = 0, ento #(S0) = 1. Isto nos informa que existe exatamente
um valor para S0. Este valor exatamente a tupla vazia, simbolizada por ( ),
que a nica tupla sem qualquer componente.
Na teoria dos conjuntos, o produto cartesiano representado da
seguinte forma:

Exemplo 2.7. Consideremos os seguintes fragmentos de programa


em Cobol e em Ada:

COBOL: Ada:
01 REGISTRO EMPREGADO. type Nome_Empregado is record
02 NOME-EMPREGADO. Primeiro : String (1..20);
05 PRIMEIRO PICTURE IS X(20). Meio : String (1..10);
05 MEIO PICTURE IS X(10). Ultimo : String (1..20);
05 ULTIMO PICTURE IS X(20). end record;
02 TAXA-HORARIA PICTURE IS type Registro_Empregado is
99V99. record
Nome : Nome_Empregado;
Taxa_Horaria : Float;
end record;
Empregado : Registro_Empregado;

Varives e Tipos de Dados 49


O tipo Empregado est mostrado na figura a seguir.

O tipo mapeamento

A noo de mapeamento de um conjunto para outro tem uma


importncia fundamental para a computao, uma vez que esta teoria
fundamenta duas estruturas importantes nas linguagens de programao:
os arrays e as funes.
Um mapeamento, m, denotado da seguinte forma:
m:ST
significando que m mapeia todo valor de S em um nico valor de T. Se m
mapeia um valor x de S em um valor y de T, denota-se isto por y = m(x), onde
y a imagem de x sob m. A notao S T utilizada para representar todos
os mapeamentos de S para T. Formalmente, escrevemos:
S T = {m | (x) x S (!y) y T y = m(x)}.
Os mapeamentos so representaes de funes. Na realidade, cada
par (x, m(x)) representa o valor de um mapeamento ou uma funo total de
um conjunto S sobre um conjunto T.
Para deduzir a cardinalidade de S T s verificar que para cada
valor em S temos #T possveis imagens. Ento existem #T x #T x ...x #T (#S
vezes), ou seja,
#(S T) = (#T)#S
Um array uma sequncia indexada de componentes. Ele tem um
componente do tipo T para cada valor de S. O tamanho de um array a
quantidade de seus componentes, que #S. Para os arrays, o conjunto S
finito e um subconjunto dos inteiros, que o conjunto de ndices. O menor
valor e o maior valor do conjunto de ndices so, respectivamente, o limite
inferior e o limite superior do array.

50 unidade 2
Graficamente, isto pode ser visto conforme a figura a seguir.

Exemplo 2.8. Considere o seguinte fragmento em C++


bool mat[3];

Esta declarao indica pelo visto anteriormente, que se trata de um


mapeamento {0, 1, 2} {false, true}. A cardinalidade deste array 23 = 8
valores. O elenco de todos os possveis valores
{{0false, 1false, 2false}, {0true, 1false, 2false},
{0false, 1false, 2true}, {0true, 1false, 2true},
{0false, 1true, 2false}, {0true, 1true, 2false},
{0false, 1true, 2true}, {0true, 1true, 2true}}

Evidente, que as funes implementadas em alguma linguagem de


programao, implementam mapeamentos. Por exemplo, o cdigo a seguir
implementa um mapeamento em C++

bool par (int n)


{ return (n % 2 == 0); }

Implementa o mapeamento Integer Bool com o seguinte conjunto


de valores:
{ ..., 0true, 1false, 2true, ...}

Vinculaes dos ndices e categorias de arrays

A vinculao dos tipos dos ndices a uma varivel array normalmente


esttica, mas as faixas de valores dos ndices, s vezes, so vinculados
dinamicamente.

Varives e Tipos de Dados 51


Em algumas linguagens de programao, o limite inferior da faixa de
ndices implcito. Por exemplo, em C, C++ e em Java, o limite inferior de
todas as faixas de ndices fixado em zero, enquanto em Fortran I, II, IV,
Fortran 77 e Fortran 90, ele fixado em 1. Em muitas linguagens, este valor
especificado pelo programador.
Os arrays ocorrem em cinco categorias. Essas categorias se
baseiam na vinculao das faixas de valor dos ndices e nas vinculaes
ao armazenamento. O nome das categorias indica onde e quando o array
alocado. So as seguintes as categorias:
Array esttico: um array esttico aquele no qual as faixas
de ndices e o armazenamento so vinculados estaticamente.
A vantagem deste tipo de array a eficincia, porque nenhuma
alocao ou desalocao feita em tempo de execuo.
Array fixo dinmico na pilha: neste tipo de array, as faixas de
ndices so vinculadas estaticamente, enquanto o armazenamento
feito durante a execuo. A sua vantagem sobre os arrays
estticos o compartilhamento de rea de memria, porque uma
matriz grande em um procedimento pode usar o mesmo espao
de memria que outra matriz, declarada em outro procedimento.
Array dinmico na pilha: neste tipo de array, as faixas de
subscritos ou ndices e o armazenamento so vinculados em
tempo de execuo. No entanto, aps esta vinculao permanece
fixo durante todo o tempo de vida da varivel. A vantagem deste
tipo de array sobre os anteriores est na flexibilidade, uma vez
que seu tamanho no precisa ser conhecido at que esteja
prestes a ser usado.
Array dinmico no heap fixo: este tipo de array similar
ao array dinmico na pilha, no sentido de que os ndices e o
armazenamento so vinculados dinamicamente, mas eles so
fixos aps a memria ser alocada. As diferenas se referem ao
fato de que as vinculaes so feitas quando o programa usurio
solicit-las, em vez de serem feitas em tempo de elaborao, e a
memria alocada no heap, em vez de ser feita na pilha.
Array dinmico no heap: este tipo de array aquele em que as
vinculaes dos ndices e a alocao de memria so dinmicas e
podem ser trocadas durante o tempo de vida do array. A vantagem
deste tipo de array sobre os outros tipos est na flexibilidade que

52 unidade 2
ele proporciona sobre os outros, uma vez que um array deste tipo
pode crescer e diminuir durante a execuo do programa.

Os arrays declarados nas funes em C e em C++ que incluem o


modificador static so arrays estticos. Se este modificador no estiver
presente nestas funes, eles so arrays dinmicos na pilha. C e C++
tambm possibilitam arrays fixos dinmicos no heap, alocados atravs das
funes malloc e calloc e liberadas atravs da funo free em C, e atravs
das funes new e delete em C++. Em Java e em C#, todos os arrays so do
tipo fixo dinmico no heap, apesar de C# tambm permitir a classe ArrayList
que prov um array dinmico no heap.

O tipo unio disjunta

Na unio disjunta um valor escolhido a partir de diversos conjuntos


possivelmente disjuntos.
A notao utilizada para a unio disjunta dos conjuntos S e T S + T,
onde os elementos deste conjunto so compostos por um rtulo para indicar
de qual conjunto o elemento escolhido, e uma parte variante que vem ou de
S ou de T. Formalmente, temos:
S + T = {left x | x S} U {right y | y T}
Neste caso, left x significa que a variante x vem do conjunto S,
enquanto right y significa que a variante y vem do conjunto T.
A cardinalidade de S + T dada por #(S + T) = #S + #T.
A unio disjunta pode ser estendida para n conjuntos, ou seja, para
S1 + S2 + ... + Sn .
A figura a seguir mostra este processo graficamente, utilizando os
diagramas de Euler-Venn da teoria dos conjuntos.

Varives e Tipos de Dados 53


Exemplo 2.9. Seja a definio de tipo a seguir em Ada
graficamente, este:

Neste exemplo, o campo Marca o rtulo. Dependendo de seu valor,


a varivel Figura_1 pode ter uma parte variante distinta. Isto significa que o
tipo figura descrito da seguinte forma:

Figura =
{Bool X Cores X Forma X Float}
+ {Bool X Cores X Forma X Integer X Integer X Float}
+ {Bool X Cores X Forma X Integer X Integer}

Possveis valores para uma varivel deste tipo podem ser:


(True, Vermelha, Circulo, 3.0), (False, Verde, Triangulo, 3, 4, 10.0),
(True, Azul, Retangulo, 5, 4), alm de outros valores. Uma representao
grfica para variveis deste tipo est mostrada na figura a seguir.

54 unidade 2
Observao importante

As unies disjuntas so tipos de dados permitidos por algumas linguagens,


mas, muitas crticas so feitas a este tipo de dado. Argumenta-se que este
tipo de dado introduz muita insegurana, dependendo da forma como ele
implementado na linguagem. Ada toma alguns cuidados em relao a isto,
e obriga que qualquer atualizao s seja permitida se for feita tambm ao
rtulo, alm de exigir que toda unio tenha o rtulo. Em Pascal, o rtulo
pode existir ou no. Se no existir torna este tipo em uma unio livre, que
o caso da linguagem C, onde a insegurana ainda maior, o que torna o
programa muito dependente do programador, sem qualquer ajuda por parte
da implementao da linguagem. Este tipo de dado se justificava em tempos
onde a economia de memria era um objetivo a ser alcanado a qualquer
custo. Nos dias atuais, as memrias tm se tornado bem mais baratas e este
objetivo perdeu muito em importncia.

Os tipos recursivos

As linguagens de programao atuais e modernas apresentam o tipo


de dado recursivo, que um dado definido em termos dele prprio. O tipo
recursivo mais comum o tipo lista, que uma sequncia de valores. Uma
lista pode ter qualquer nmero de componentes, inclusive nenhum, que o
caso das listas vazias. Uma lista um tipo de dado homogneo, ou seja,
todos os seus componentes so do mesmo tipo, apesar de cada componente
poder ser de um tipo heterogneo, como um registro, por exemplo.
Suponha que se deseja construir uma lista de valores inteiros. Neste
caso, a lista ou a lista vazia; ou constituda de um valor inteiro, sua

Varives e Tipos de Dados 55


cabea, e de uma lista que pode ser vazia ou no, conhecida como a cauda
da lista. Esta definio , por natureza, recursiva:
Lista_int = nil Unit + cons (Integer X Lista_int)
De outra forma:
Lista_int = {nil ( )} U {cons (i, l) | i Integer, l Lista_int
Onde nil e cons so apenas rtulos para a lista vazia e para a lista
no vazia, respectivamente.
Normalmente, a notao nil ( ) abreviada para apenas nil. De forma
generalizada, temos: L = Unit + (T X L) que representa o conjunto de todas
as listas finitas de valores do tipo T. O tipo lista tem tanta importncia que se
dedicou a notao T* = Unit + (T X T*) para ele, que nada mais do que uma
nova forma de representao da mesma entidade abstrata.

Exemplo 2.10. Em Haskell, uma linguagem de programao funcional


muito utilizada atualmente, uma lista de inteiros pode ser definida da seguinte
forma:
data Lista_int = Nil | Cons Int Lista_int
Neste caso, a lista [3,6,9] representa Cons 3 (Cons 6 (Cons 9 Nil)).
Haskell tem diversos tipos pr-definidos na linguagem, por exemplo, [Int],
[String], [[Int]] que representam a lista de inteiros, a lista de Strings e a lista
de listas de inteiros. Em Haskell tambm possvel que uma lista tenha um
tipo polimrfico. Por exemplo, [t] representa uma lista de qualquer tipo.

Exemplo 2.11. Uma rvore binria uma estrutura de dados


que pode ser definida de forma fcil e natural em Haskell da seguinte
forma:
data ArvBin t = Folha t | No (ArvBin t) (ArvBin t)
Nesta definio, cada elemento ou um n externo (uma Folha
com um valor do tipo t) ou um n interno, sem um valor armazenado,
mas com duas subrvores binrias como sucessoras para este n.
Por exemplo, a rvore binria No (Folha 14) (No (Folha 09) (Folha
51)) pode ser representada, graficamente, como na figura ao lado.

O tipo String

Todos os tipos de dados foram vistos e analisados at o presente


momento desta unidade. No entanto, cabe uma observao sobre o tipo

56 unidade 2
String.
Um String uma sequncia de caracteres, podendo ter qualquer
nmero destes, inclusive nenhum. A quantidade de caracteres de um String
o tamanho do String. O nico String que no tem qualquer caractere o
String vazio.
No entanto, no existe um consenso entre os projetistas de linguagens
sobre qual deve ser a forma de implementao dos Strings.
Alguns projetistas defendem que os Strings sejam implementados
como tipos primitivos da linguagem. Neste caso, as operaes sobre eles
seriam pr-definidas e no seriam definidas na linguagem, e eles poderiam
ter qualquer tamanho. A linguagem funcional ML adota esta tcnica.
Uma outra metodologia que tem sido defendida por outros projetistas
considerar os Strings como arrays de caracteres. Neste caso, todas as
operaes implementadas para os arrays, podem ser aplicadas aos Strings.
Em particular, a seleo de um caractere um caso de indexao que
uma operao prevista para os arrays. Uma consequncia direta desta
metodologia que todos os Strings devem ter um seus tamanhos fixados,
porque os tamanhos dos arrays so fixados no momento em que eles so
construdos. Isto proibiria que a linguagem permitisse arrays de tamanhos
flexveis. Esta tcnica adotada pela linguagem Ada.
Uma terceira verso destes tipos trata os Strings como arrays de
ponteiros para caracteres, que a tcnica adotada por C e C++. Esta tcnica
permite uma grande economia de memria e um desempenho bem melhor no
tratamento de variveis com valores destes tipos. Deve ser esclarecido que as
implementaes, normalmente, so transparentes aos programadores, que
no devem preocupar-se com a corretude no processamento de operaes
com ponteiros, por ser uma tarefa que exige uma boa experincia por parte
do profissional neste tratamento.
A nosso juzo, se a linguagem de programao oferece o tipo lista,
natural implementar os Strings como listas de caracteres. Neste caso, todas
as operaes que so implementadas para as listas podem ser utilizadas nos
Strings. Esta a tcnica utilizada por Haskell, onde uma varivel String com
valor UFPI tem o mesmo significado que a lista [U, F, P, I].

Equivalncia de tipos

Em diversas situaes, devemos decidir se dois objetos so do mesmo

Varives e Tipos de Dados 57


tipo, ou se so de tipos equivalentes, para que possam ser usados em uma
determinada construo de linguagem. A forma da resposta depende, claro,
da linguagem, que deve definir suas prprias regras de equivalncia de tipos.
As duas formas fundamentais de equivalncia so: a equivalncia
nominal (dois tipos so equivalentes se tm o mesmo nome) e a equivalncia
estrutural (independentemente de seus nomes, dois tipos so equivalentes
se tm a mesma estrutura, isto , se so construdos da mesma maneira a
partir dos mesmos tipos). Naturalmente, a primeira forma de equivalncia
(nominal) sempre acarreta a outra (estrutural).
Assim, os tipos das variveis x1 e x2, do Exemplo 2.12, a seguir, so
estruturalmente equivalentes, mas no so nominalmente equivalentes; os
tipos de x1 e y1 so equivalentes pelos dois critrios.
Exemplo 2.12. Seja o fragmento de cdigo a seguir:
type
t1 = array [1..10] of integer;
t2 = array [1..10] of integer;
var
x1, y1 : t1;
x2 : t2;

A linguagem Algol-68 utiliza a equivalncia estrutural, cuja


implementao considerada um pouco mais trabalhosa: se dois tipos no
tem o mesmo nome, necessrio verificar suas estruturas, num teste que pode
envolver a verificao da equivalncia de vrios outros tipos, componentes
dos tipos cuja equivalncia se quer determinar.
Por outro lado, j observamos que a linguagem Ada adota a
equivalncia nominal. Ada considera de tipos distintos at mesmo duas
variveis introduzidas na mesma declarao: a declarao
x, y : array (1..10) of integer;
faz com que as variveis x e y tenham tipos annimos, que, portanto, no tem
o mesmo nome.
Voltando ao caso bem conhecido de Pascal (cuja especificao
no fixa, claramente, a forma de equivalncia), temos, normalmente,
implementaes que misturam as duas formas de equivalncia. Usando a
equivalncia estrutural a maior parte do tempo, e os nomes dos tipos nas
especificaes de tipos de parmetros e resultado de procedimentos e
funes. Em particular, inconsistentemente, valores de variveis de tipos
intervalo so tratados como pertencendo ao tipo base, sendo as restries

58 unidade 2
verificadas apenas em tempo de execuo, como seria correto se intervalos
fossem apenas subtipos, como em Ada.
Diz-se que uma linguagem fortemente tipada, se possvel, apenas
por anlise esttica do programa (anlise realizada em tempo de compilao)
determinar que a estrutura de tipos da linguagem no violada. Exemplos de
linguagens fortemente tipadas so Algol-68 e Ada; Pascal seria fortemente
tipada com algumas pequenas modificaes, tais como a definio de tipos
procedimento e a definio de subtipos intervalo.
Note-se que, a rigor, linguagens como Snobol e Smalltalk, cuja
definio e implementao absolutamente no prev verificao esttica de
tipos, podem ser consideradas (trivialmente) linguagens fortemente tipadas:
basta considerar que todos os valores considerados na linguagem so do
mesmo tipo (string em snobol e objeto em Smalltalk). , assim, impossvel
cometer erros de tipagem, e, portanto, de forma trivial, todos os erros de
tipagem podem ser detectados estaticamente. Ou seja, a propriedade
de tipagem forte em linguagens de programao tem uma importncia
dependente da sofisticao do sistema de tipos oferecido pela linguagem.

Converso de tipos

Se necessitarmos, em alguma situao, de um valor de um tipo t1,


e apenas est disponvel um valor de um tipo t2, pode ser necessria uma
converso de tipo. Vamos examinar algumas dessas situaes que podem
ocorrer em conjunto, em uma mesma linguagem.
Converso implcita. Neste caso, considerando-se a situao
do ponto de vista abstrato, os valores do tipo t1 so valores do
tipo t2, embora a representao de um valor x de t1 possa ser
distinta da representao do mesmo valor x de t2. Este o caso
de inteiros e reais: abstratamente, os reais contm os inteiros,
embora as representaes internas possam ser distintas. Esta
uma converso implcita, isto , sua necessidade no precisa ser
indicada pelo programador. Por exemplo, a maioria das linguagens
aceita um comando x := i; mesmo quando x uma varivel real,
e i uma varivel inteira. O cdigo de converso (por exemplo,
do valor inteiro de i para o real equivalente) quando necessrio,
deve ser includo pelo compilador. Esta forma de converso , s
vezes, conhecida como coero.

Varives e Tipos de Dados 59


Converso explcita. Quando h vrias maneiras de converter
um valor de um tipo t1 para o tipo t2, necessrio indicar a forma
de converso desejada, e, em geral, isso feito atravs de uma
funo de converso. Este o caso da converso de reais em
inteiros, que pode ser feita por arredondamento, truncamento,
etc. Normalmente, funes pr-definidas da linguagem esto
disponveis para as situaes mais comuns, incluindo casos como
arredondamento, truncamento, aproximao superior (ceiling) ou
inferior (floor).
Converso formal. Neste caso, preciso que a converso seja
indicada, por causa do controle de tipos da linguagem, mas
nenhum cdigo precisa ser executado. Isto acontece quando
temos tipos diferentes, cuja representao interna, entretanto,
a mesma. Este o caso da funo chr de Pascal, que, nas
implementaes usuais, no executa nenhum cdigo, j que um
caracter chr(i) representado internamente pelo inteiro i.
Converso forada. Por vrias razes, o programador deseja
que um valor do tipo t1 seja entendido como se fosse do tipo t2.
No se trata, seno formalmente, de converso, uma vez que
aqui, o que se deseja enganar o compilador, o qual deve ser
avisado que o valor do tipo t1 deve ser aceito como se fosse do
tipo t2. Tais mecanismos se encontram em algumas linguagens,
e seu uso de exclusiva responsabilidade do programador. Em
Modula-2 o nome do tipo usado como se fosse uma funo
de converso; em C, o mesmo efeito pode ser obtido atravs da
construo sinttica conhecida como typecast (molde).

Exerccio

1. Quais os principais atributos das variveis nos programas codificados nas


diversas linguagens de programao?

2. Qual o papel da vinculao nas variveis dos programas de computador?

3. Que importncia tem as regras de escopo na execuo dos programas?

60 unidade 2
4. Quais tipos de dados representam as estruturas, as unies e os vetores
em C?

5. Que tipos de dados a linguagem Java apresenta?

6. Que tipos de dados as matrizes bi-dimensionais representam?

SAIBA MAIS

Existem muitos bons textos e alguns deles esto listados em Referncias


colocadas ao final da Unidade 2. Outros esto na Internet disposio.
UNIDADE 3
Controle de Fluxo

Resumindo
O objetivo principal desta unidade apresentar ao leitor os principais conceitos referentes ao
controle do fluxo de um programa durante a sua execuo. Este controle pode se dar em trs
nveis: no nvel das expresses, no nvel das instrues e no nvel dos subprogramas. No nvel
das expresses, este controle guiado pelas regras de precedncia e pela associatividade dos
operadores aritmticos. No nvel de instruo, o controle feito pelas instrues de se; seleo e
de iterao que pode ser controlada por contadores ou por uma expresso lgica ou booleana. No
nvel dos subprogramas, o controle executado pelo sistema de execuo que composto pela
pilha do sistema que utilizada em cada chamada e em retornos de chamadas a subprogramas. A
forma de apresentao utilizada de acordo com o exigido para o ensino a distncia, ou seja, tendo
em vista sempre esta nova modalidade de ensino.
controle de fluxo

Introduo

A primeira forma de controle da execuo de um programa acontece


na avaliao das expresses. Neste caso, o controle feito baseado nas
regras de precedncia e nas regras de associatividade dos operadores
envolvidos na expresso.
A segunda forma de se controlar a execuo de um programa se
d na execuo das instrues. Neste caso, o controle se d pela escolha
da prxima instruo a ser executada. Quem comanda este controle so
os comandos de seleo e de iterao que podem ser controlados por
expresses lgicas ou por contadores.
A terceira forma de controle da execuo de um programa acontece
no nvel de subprogramas. Neste caso, a pilha do sistema de execuo
utilizada para proceder a chamada e o retorno de cada subprograma.
Nesta unidade, estes temas sero analisados em detalhes.

Controle de execuo em nvel de expresses

Para entender a avaliao das expresses necessrio entender


as ordens de avaliao dos operadores e dos operandos que compem as
expresses. A ordem de avaliao dos operadores regida pelas regras de
precedncia e associatividade utilizadas na linguagem. Normalmente, as
regras adotadas na Matemtica so respeitadas, tambm, no processo de
avaliao das expresses feitas pelos compiladores, mas isso no uma
verdade absoluta, uma vez que existem algumas linguagens que no seguem
este princpio.

Controle de Fluxo 65
Avaliao de expresses aritmticas

Como j afirmado anteriormente, a maioria das caractersticas das


expresses aritmticas nas linguagens de programao foi herdada de
convenes desenvolvidas na Matemtica. Nas linguagens de programao,
as expresses aritmticas consistem de operadores, operandos, parnteses
e chamadas a funes. Os operadores necessitam de operandos para que
possam ser avaliados. A quantidade dos operandos que cada operador
aritmtico precisa para ser avaliado conhecida como a sua aridade. Que
pode ser unria, binria ou, mais raramente, ternria, conforme tenham um,
dois ou trs operandos, respectivamente.
Na maioria das linguagens imperativas, os operadores binrios so
infixos, ou seja, eles so colocados entre seus operandos. No entanto,
eles podem ser pr-fixos, se forem colocados antes de seus operandos, ou
podem ainda serem ps-fixos se forem colocados aps os seus operandos.
As operaes ps-fixas obedecem a uma notao conhecida como notao
polonesa reversa. A linguagem Perl apresenta alguns operadores pr-fixos.

Exemplo 3.1. A expresso (8 * ((5 + 4) 10)) / 20 tem as seguintes


formas de representao:
(8 * ((5 + 4) 10)) / 20 Notao infixa
/ * 8 - + 5 4 10 20 Notao pr-fixa
8 5 4 + 10 - * 20 / Notao ps-fixa

Precedncia de operadores

O valor de uma expresso depende, pelo menos em parte, da ordem


de avaliao dos operadores na expresso. Por exemplo, em um contexto em
que a = 3, b = 4 e c = 5 analisemos a expresso a + b * c.
Se a avaliao se proceder da esquerda para a direita, a soma ser
feita primeiro e depois a multiplicao. Neste caso o valor final ser 35. Se, por
outro lado, a avaliao se processar da direita para a esquerda, a multiplicao
ser realizada primeiramente e depois ser feita a soma. Neste caso, a
avaliao ter o valor 23. Um valor diferente do encontrado anteriormente.
Mas qual o valor correto para esta expresso? Os matemticos decidiram
que uma expresso deste tipo no deve ser avaliada, nem totalmente pela
esquerda, nem totalmente pela direita. Eles criaram a ideia de precedncia

66 unidade 3
dos operadores. Neste caso, a operao de multiplicao tem precedncia
sobre a operao de adio. Para a expresso citada, o valor correto seria
23.
As regras de precedncia adotadas pela Computao, normalmente,
obedecem s regras de precedncia estabelecidas pela Matemtica, mas
esta no uma deciso obrigatria. A tabela a seguir apresenta algumas
linguagens e as regras de precedncia adotadas por cada uma delas, onde
a operao mais acima na tabela significa que o seu grau de precedncia
maior que o de uma operao que esteja situada mais abaixo na tabela.

Fortran Linguagens baseadas em C Ada


** ps-fixa ++, -- ++, abs
*, / pr-fixa ++, --, + e - unrios *, /, mod, rem
todos + e - *, /, % unrios +, -
binrios +, - binrios +, -

O operador ** a exponenciao. O operador % de C o mesmo
operador rem de Ada, que toma dois operandos inteiros e retorna o resto da
diviso do primeiro pelo segundo valor. O operador mod de Ada idntico a
rem quando ambos operandos forem positivos.
Deve ser notado que a linguagem APL tem uma deciso sui-generis
sobre este tema. Ela apresenta um nico nvel de precedncia que o mtodo
de avaliao da direita para esquerda.

Associatividade de operadores

A associatividade de operadores entra em cena na deciso de que


operador deve ser escolhido se eles tiverem o mesmo nvel de prioridade. Por
exemplo, vamos analisar a expresso a b + c d em que as operaes e
+ tm os mesmos nveis de prioridade. Neste caso, deve-se fazer a subtrao
primeiro, ou a operao de soma? As regras de associatividade respondem
a esta questo da seguinte forma. Normalmente, a associatividade utilizada
pelos operadores feita pela esquerda, exceto, quando o operador
a exponenciao. Neste caso, no exemplo em voga, a subtrao a b
realizada inicialmente, depois, soma-se esse resultado com c e finalmente
diminui-se deste resultado, que ser o valor final da expresso.
Alguns dados:

Controle de Fluxo 67
O operador de exponenciao em Fortran associativo pela
direita, ou seja, na expresso A ** B ** C, avalia-se inicialmente
B ** C.
Em Ada a exponenciao no associativa, ou seja, a expresso
a ** b ** c ambgua e no legal. Deve-se usar parnteses para
resolver esta ambiguidade.
A tabela a seguir mostra as regras de associatividade adotadas por
algumas linguagens de programao.

Fortran Linguagens baseadas em C Ada


Esquerda *, /, +, - *, /, %, +, - menos**
Direita ** ++. --, +, - unrio **

Deve ser lembrado, aqui, que as regras de precedncia e


associatividade podem ser alteradas pela utilizao de parnteses que tm
prioridade sobre todas elas.

Ordem de avaliao dos operandos

Em uma operao com mais de um operando necessrio estabelecer


qual a ordem em que os operandos devem ser avaliados. Se nenhum dos
operandos tiver efeitos colaterais, a ordem de avaliao no ter qualquer
influncia sobre o resultado final da operao. No entanto, se tiver algum
efeito colateral na avaliao de algum operando, a ordem de avaliao dos
operandos pode resultar em valores distintos.

Exemplo 3.2. Analisemos o programa a seguir, em C, admitindo que


a funo fun seja definida da seguinte forma:
int fun(int *i) {
*i += 5;
return 4;
}
void main( ) {
int x = 3;
x = x + fun(&x);
}

68 unidade 3
Qual o valor da varivel x exatamente antes do final da execuo
deste programa? A resposta a esta questo pode parecer bvia para quem
no sabe que a ordem em que os operandos so avaliados tem influncia
no resultado final, neste caso. Se o operando a do operador + for avaliado
primeiro, o resultado ser 7. No entanto, pode ser que o operando fun(&x)
seja avaliado inicialmente. Neste caso, a aplicao fun tem o efeito colateral
de modificar o valor da varivel x para 8. A soma do valor de retorno 4, com
o valor de x que agora 8, totaliza um valor igual a 12.

Converso de tipos

Nas linguagens de programao podem acontecer dois tipos de


converso de tipos. So eles: estreitamento e alargamento. Uma converso
de estreitamento transforma um valor em outro valor, de um tipo que no
pode armazenar nem mesmo aproximaes de todos os valores do original.
Um exemplo deste tipo de converso acontece em C, na converso de um
tipo double para um tipo float, onde a faixa de um tipo double bem maior
que a faixa de um tipo float.
J, em uma converso de alargamento, um valor de um tipo convertido
em um valor de outro tipo que pode incluir, pelo menos, aproximaes de
todos os valores do tipo original. Um exemplo deste tipo de converso ocorre
ao se converter um valor do tipo int em um valor do tipo double, em C.
As converses podem acontecer de forma explcita, feita pelo
usurio, ou pode ser feita de forma implcita pelo compilador. Neste caso,
o processo acontece de forma ortogonal e transparente ao programador. No
entanto, necessrio que o programador conhea e domine os detalhes
ocultos nos dois tipos de converso para que seja capaz de fazer e construir
programas mais confiveis e com bom desempenho, evitando a ocorrncia
de sobrecargas em tempo de execuo e que poderiam ser evitadas.

Operaes de modo misto

Algumas linguagens de programao permitem que o programador


possa codificar uma operao binria, onde um dos operandos tenha um tipo
e o outro operando seja de outro tipo. Uma operao com estas caractersticas
uma operao de modo misto.
Nos computadores atuais, os circuitos dedicados ao processamento

Controle de Fluxo 69
de operaes binrias so construdos de forma que s possvel realizar
operaes binrias em que os dois operandos sejam do mesmo tipo. Isso
significa que os circuitos para realizar uma soma de inteiros, exigem que
os valores a serem somados sejam ambos do tipo inteiro. De forma similar,
tambm possvel somar dois nmeros reais, e os circuitos computacionais
so feitos, de tal forma, que esta operao s seja possvel se ambos os
valores de entrada forem nmeros reais. Dito de outra forma, s possvel
realizar operaes binrias com valores do mesmo tipo.
Se for declarada uma operao binria a ser realizada com argumentos
de tipos distintos, um dos valores ter que ser convertido para o tipo do outro,
para que a operao possa ser realizada.
Por exemplo, se uma linguagem permitir a codificao da expresso
4.0 + 3, ou seja, a soma de um nmero real com um nmero inteiro, ento,
dever acontecer uma converso do valor 4.0 para um nmero inteiro
para que seja somado com o valor inteiro 3; ou, o valor inteiro 3 deve ser
convertido em um valor real para que possa ser somado com o valor 4.0.
Este tipo de converso implcita, e realizada pelo compilador de forma
transparente, sem que o programador tome conhecimento deste fato. Este
tipo de converso conhecida como coero.
C++ e Java tm tipos inteiros menores que o tipo inteiro int. Em
C++, eles so char e short int; em Java, eles so byte, short e char. Tais
operandos so coagidos para o tipo int quando qualquer operador for aplicado
a eles. Embora dados possam ser armazenados em variveis desses tipos,
eles no podem ser manipulados, antes de serem convertidos para outro
maior.
Exemplo 3.3. Considere o seguinte cdigo em Java:
byte x, y, z;
...
x = y + z;

Neste caso, as variveis y e z so coagidas para o tipo int antes


de ser realizada a operao de soma. Aps a soma ser realizada, o valor
novamente coagido para um valor inteiro e atribudo a x.

Converso de tipo explcita

A grande maioria das linguagens de programao permite alguma


forma de converso explcita, podendo ser de estreitamento ou de alargamento.

70 unidade 3
Nas linguagens baseadas em C, as converses explcitas so
conhecidas como casts. Para se especificar um cast, o tipo desejado deve
ser colocado entre parnteses antes da expresso a ser convertida. Por
exemplo, a declarao (int) contador; o motivo da colocao dos parnteses
que C tem vrios tipos com mais de uma palavra, por exemplo, long int.
Em Ada, a converso explcita tem a sintaxe das chamadas de funes. Por
exemplo, Float (soma).

Avaliao curto-circuito

Uma avaliao curto-circuito acontece em algumas linguagens, onde


uma expresso no precisa avaliar todos os seus operandos para se chegar
a um resultado. Por exemplo, o valor da expresso (19 * x) * (y /123 -32)
independe do valor da expresso (y /123 -32) se x = 0. Porque o primeiro
termo, 19 * x 0 e 0*qualquer valor finito 0, independente de que valor seja
este. Entretanto, este atalho difcil de ser detectado e, por este motivo,
ele nunca realizado. No entanto, este tipo de atalho mais fcil de ser
detectado em expresses booleanas. Por exemplo, seja a expresso:
(x >= 0) and (y > 20)
Se x < 0, o resultado da expresso ser false, independente do
segundo operando da expresso, porque false and x = false, independente
do valor de x.
Para ilustrar o problema potencial em avaliao de expresses
booleanas, sem usar operaes curto-circuito. Suponha que Java no
implemente este tipo de operao e imagine uma lista de tamanho tam e
codifique um fragmento de cdigo para realizar uma busca linear nesta lista.
O fragmento de cdigo pode ser o seguinte:
ndice = 0;
while ((ndice < tam) && (lista[ndice] <> chave))
ndice ++;

Se no for usada a avaliao curto-circuito, os dois operandos da


operao && sero avaliados. Neste caso, se a chave no estiver na lista,
o primeiro argumento de && quando o ltimo elemento da lista for analisado
ser avaliado como true, mas o valor de ndice ser incrementado, e, na
prxima iterao, o primeiro argumento ter o valor false. Como a operao
curto- circuito no realizada, o segundo argumento ser tambm analisado.

Controle de Fluxo 71
S que o valor de ndice est fora dos limites da lista, e este teste ser feito
sobre um valor que no est na lista.

Controle de fluxo em nvel de instrues

As instrues de um programa so executadas em ordem sequencial,


exceto, pelas instrues de desvios, que podem transferir o controle da
execuo de um ponto para outro na mesma unidade de programa, ou em
outra. Os mecanismos de transferncia entre unidades sero objeto da
prxima seo.
Os mecanismos internos de transferncia mais simples de serem
implementados so os desvios explcitos, condicionais ou incondicionais,
para pontos do programa indicados por rtulos a eles associados.
Entretanto, apesar de ser fcil compreender o efeito da execuo
de um destes comandos, muito difcil visualizar o efeito de um trecho de
programa onde vrios destes comandos sejam utilizados, quando esses
programas podem ser comparados a pratos de espaguete.
Para evitar esta dificuldade, foram introduzidos os comandos
estruturados, que dispensam o uso de rtulos indicativos de posies dentro
de uma unidade de programa, e cujo efeito mais fcil de ser entendido e
descrito, simplesmente porque correspondem a construes habitualmente
usadas.
Essencialmente, um comando estruturado se caracteriza por uma
estrutura recursiva (pode ser composto de outros comandos menores). Um
nico ponto de entrada, um nico ponto de sada, e, um efeito descrito em
termos da seleo ou da repetio dos efeitos dos comandos componentes,
dispensando o uso de rtulos como referncias a pontos do programa. Essas
estruturas recursivas tm sido tambm usadas em especificao informal
de programas, por exemplo, em diversas formas de pseudocdigo, cuja
finalidade servir de orientao, mais ou menos detalhada, ao programador
do cdigo.

Desvios explcitos

O desvio explcito e incondicional representado pelo comando goto,


presente na maioria das linguagens, sendo ele o exemplo mais conhecido
de comando no estruturado. O comando do Fortran, conhecido como IF

72 unidade 3
aritmtico, tambm tem merecido ateno, mas de forma menos enftica. O
IF aritmtico do Fortran tem a seguinte sintaxe:
IF ( <expresso> ) <rtulo-1>, <rtulo-2>, <rtulo-3>
indica a transferncia de controle para os comandos indicados pelos
rtulos <rtulo-1>, <rtulo-2>, <rtulo-3>, conforme o valor de expresso
seja, respectivamente, negativo, nulo ou positivo. As linguagens modernas
apresentam formas alternativas de comando IF, que so preferveis a estas
construes. Em alguns casos, como em Fortran-77, ambas as formas
coexistem na linguagem.

Comandos de seleo

A forma mais simples de comando de seleo o comando IF de


Algol ou de Pascal, que permite a execuo condicional de um comando ou
escolher entre duas alternativas. Linguagens como Algol-68, Modula-2 e Ada
oferecem um comando IF fechado, em que as alternativas podem ser listas
de comandos, e em que mais de duas alternativas podem ser oferecidas.
Este tipo de estrutura , s vezes, chamado de estrutura de pente, sendo
marcas como if, elsif e end if usadas para definir os dentes do pente, entre
os quais se introduzem os comandos. A forma mostrada na figura a seguir
adotada em Ada:

Controle de Fluxo 73
A tabela a seguir mostra a equivalncia entre as formas do comando
IF de Ada e uma escadinha de IFs em Pascal. Note que, quando a lista de
comandos em Ada contm mais de um comando, necessrio usar um
comando composto em Pascal.

Ada Pascal
if c1 then if c1 then
s1 s1
elsif c2 then else if c2 then
s2; s2
elsif c3 then else if c3 then
s3; begin
s4; s3;
s4
else end
s5; else
end if ; s5;

A sintaxe varia um pouco de uma linguagem para outra. No caso de


Algol-68, a sintaxe do comando if se aplica tambm expresses, uma vez
que, comandos e expresses se confundem nessa linguagem. Por exemplo,
em Algol-68, a expresso condicional: if a=b then c else d fi; ter como
resultado c ou d, dependendo do resultado da avaliao da condio a = b.
Um caso especial o dos comandos case, ou switch onde as
alternativas de execuo so definidas pelos valores possveis de uma
expresso. O comando case de Pascal tambm pode ser substitudo por um
conjunto de ifs aninhados.

74 unidade 3
Usando o comando case Usando ifs aninhados
case exp of v:=exp;
if v=v1 then
v1 : c1; c1
v2 : c2; else if v=v2 then
c2
v3 : c3; else if v=v3 then
... c3
end; ...

No exemplo acima, exp uma expresso; v1, v2, v3 so os


valores esperados de exp; c1, c2, c3, .... so as alternativas de comandos
correspondentes. A varivel temporria v usada apenas para evitar que a
expresso seja calculada mais de uma vez.
Outras linguagens acrescentam uma alternativa (else em Modula-2,
otherwise em PL/I, others em Ada, default no comando switch em C), para o
caso em que exp no tenha qualquer dos valores v1, v2, v3, ... Alm disso,
normalmente, so permitidos intervalos de valores como opes. No caso
do comando switch da linguagem C, devemos observar que a semntica
envolvida diferente, como pode se ver no exemplo a seguir.

Exemplo 3.4. Seja a declarao a seguir de uma seleo switch em


C:
switch ( exp ) {
case v1: s1;
case v2: s2;
case v3: s3; break;
case v4: s4; break;
default: s5;
}

Neste exemplo, verifica-se a presena do comando break nas


alternativas v3 e v4. A sua finalidade, neste caso, encerrar a execuo do
comando switch. Como no caso de Pascal, a expresso exp s avaliada
uma vez, mas, diferentemente da metodologia ali adotada, mais de uma
alternativa pode ser escolhida em uma mesma execuo do comando. O

Controle de Fluxo 75
uso do comando break necessrio para finalizar o switch nesta linguagem.
Suponha que exp tenha o valor v2, e que os quatro valores v1, v2, v3 e v4
sejam todos distintos. Neste caso, a execuo se realiza da seguinte forma:

a expresso exp avaliada, obtendo-se o valor v2;


compara-se o valor de exp com v1; como so diferentes, passa-
se ao teste seguinte (at encontrar um valor igual ou o rtulo
default);
compara-se o valor de exp com v2; como so iguais, s2
executado;
a execuo continua no comando seguinte, s3;
ao chegar ao comando break a execuo do comando switch
interrompida, continuando a execuo do programa a partir da
instruo seguinte a ele.

Para C, portanto, a lista de comandos dentro do comando switch


apenas uma lista de comandos rotulados, que devem ser executados em
sequncia, exceto, por dois pontos:

o primeiro comando a ser executado aquele rotulado pelo


valor da expresso, ou por default, se o valor da expresso no
corresponder a nenhuma alternativa;
o comando break, se estiver presente, encerra a execuo do
comando switch inteiro. Isto no um privilgio do comando switch;
o comando break pode tambm ser utilizado para interromper a
execuo de outros comandos da linguagem.

O comando case pode ser implementado de forma semelhante


ao aninhamento de ifs, ou seja, por comparaes sucessivas com os
diversos rtulos, ou atravs de uma tabela de desvios para os comandos
correspondentes, indexada pelo valor da expresso. A execuo mais
rpida neste segundo caso, porque depois de avaliar a expresso, basta
desviar para o endereo correspondente na tabela.
A principal vantagem deste comando o aumento de legibilidade, que
fica muito prejudicada quando necessrio considerar um grande nmero de
alternativas usando comandos if.

76 unidade 3
Execuo iterativa de instrues

As instrues de iterao consistem em fazer com que uma instruo


ou um conjunto delas, seja executada, zero, uma ou mais de uma vez. Todas
as linguagens imperativas incluem um ou mais tipos de iterao. Se este tipo
de instruo no existisse, o programador teria que declarar cada ao em
sequncia e os programas seriam muito grandes e demorariam muito tempo
para serem codificados.
Uma construo de iterao composta de uma instruo de
iterao e de um corpo do lao que a coleo de instrues controladas
pela instruo de iterao.
Nas linguagens imperativas, a execuo do corpo do loop pode
ser controlada por uma expresso booleana, por um contador ou por uma
combinao destes dois mtodos.
Nas linguagens funcionais, como Haskell, as execues iterativas
so controladas atravs da definio de funes recursivas.
Nas instrues iterativas onde o controle seja feito por uma expresso
lgica, o controle da iterao pode ser feito antes ou depois da execuo do
corpo do lao. Se for realizado antes, o mecanismo de controle conhecido
como pr-teste e se for feito aps a execuo do corpo do lao, ser chamado
de ps-teste.
Nos comandos de repetio, desejamos a execuo repetida, de forma
controlada, de uma ao ou srie de aes. A ao indicada executada, ou
enquanto se mantiver verdadeira uma condio de continuao, ou enquanto
uma condio de trmino se mantiver falsa. Nesta seo, sero discutidos os
seguintes comandos de repetio: while, repeat, loop e for.

Loops controlados por expresses lgicas

Um comando while exp do c; precede cada execuo do comando


c pela avaliao e teste do valor da expresso exp; c s executado se o
valor de exp for true. Portanto, exp especifica uma condio de continuao
da repetio. Como no caso do if, algumas linguagens usam uma construo
fechada, em que c pode ser uma lista de comandos: while exp do c end.
Um comando semelhante o comando do-while que definido por
do c while exp; que difere do comando anterior pelo fato de que c sempre
executado uma primeira vez. Por seu lado, no comando repeat c until exp, a

Controle de Fluxo 77
expresso exp uma condio de trmino: a repetio continua at que exp
se torne verdadeira. Tambm neste caso, a lista de comandos c sempre
executada pelo menos uma vez.
At certo ponto, possvel intercambiar os usos dos comandos repeat
e while, pela negao da expresso e. Assim, um comando repeat c until exp
equivalente sequncia de comandos
c;
while not exp do
c
e o comando while exp do c equivalente combinao
if exp then
repeat
c
until not exp

Loops controlados por contadores

Por outro lado, as instrues de iterativas podem ser controladas por


um ou mais contadores. Por exemplo, o comando
for v := e1 to e2 do c
tem sua execuo controlada pelos valores da varivel v, conhecida como a
varivel de controle do for. Inicialmente, os valores v1 e v2 de e1 e e2 so
obtidos. Se v1<v2, c executado uma vez para cada valor v=v1, v=v2; caso
contrrio, c no executado nenhuma vez. O comando for equivalente a:
inf := e1;
sup := e2;
v1 := inf;
while v <= sup do begin
c;
v := v + 1;
end;
onde inf e sup so variveis temporrias, que garantem que as expresses
e1 e e2 sejam avaliadas apenas uma vez.
Com esta definio (usada em Pascal) vemos que, se n > 0,
for v := 1 to n do c
especifica a execuo de c exatamente n vezes. No caso do comando do
de Fortran, isto no ocorre: a lista de comandos sempre executada pelo

78 unidade 3
menos uma vez. Em Algol-60, podemos definir, atravs da clusula step s,
que o passo, isto , o incremento da varivel do for a cada interao deve ser
s. Em Pascal, existem apenas duas opes de passo: +1, indicado pelo uso
de to, como acima, e -1, indicada pelo uso da palavra downto, caso em que a
varivel de controle assume, sucessivamente, valores decrescentes.
O comando For visto acima, se distingue fundamentalmente dos
comandos while e repeat, pelo fato de que no For as expresses so pr-
calculadas, e o nmero de execues conhecido, a priori, enquanto, no caso
dos comandos while e Repeat, as expresses so reavaliadas a cada vez.
Linguagens como Ada e Clu consideram que a varivel v do For declarada
pelo cabealho, e , portanto, local ao comando. Nessas linguagens no h
nenhuma indeterminao quanto ao valor da varivel v aps a execuo do
comando: esse valor no existe. Outras linguagens costumam indicar que a
varivel do FOR tem um valor indefinido aps a execuo do comando, para
que possa ser escolhida, em cada caso, a melhor forma de implementao.
Em Algol-60, por exemplo, encontramos vrias outras formas
de comando For. Em particular, possvel especificar uma condio de
continuao, atravs de uma clusula while e3, em vez de especificar um
valor final para a varivel: a execuo do comando se encerra quando a
avaliao de e3 levar a um valor falso
for v:= e1 step e2 while e3 do c
As duas formas podem ser combinadas:
for v:= e1 step e2 while e3 until e4 do c
A linguagem C apresenta um comando For que separa claramente os
seus quatro componentes:
for ( e1; e2; e3 ) s
onde:
e1 especifica a forma de iniciao;
e2 especifica a condio de continuao (a execuo continua
enquanto a avaliao de e2 obtiver um valor interpretado como
true);
e3 prepara a execuo da prxima iterao, por exemplo
incrementando o valor de uma varivel de controle;
s o comando a ser repetidamente executado.

Por exemplo, para executar o comando s para os valores 1,2, ... , n


da varivel i, teramos:

Controle de Fluxo 79
for ( i=1; i<=n; i++ ) s.
Considerado extremamente poderoso pelos programadores de C,
este comando bem caracterstico do estilo compacto de programao da
linguagem C, e, juntamente com outros comandos da linguagem, tem sido
criticado por levar a programas obscuros, dependendo de sua forma de
utilizao.

Os comandos Loop e Exit

Em algumas situaes, os comandos de repetio j apresentados


so inadequados para refletir a estrutura desejada. Por essa razo, algumas
linguagens (Ada, Modula-2, por exemplo) introduzem um comando de repetio
indefinida loop, cuja execuo s deve ser interrompida por um comando
exit, que transfere o controle da execuo para o ponto imediatamente aps o
loop, terminando assim sua execuo. No caso geral, a combinao loop-exit
no tem equivalentes simples em termos de while e repeat. A combinao
loop-exit satisfaz os requisitos mencionados para um comando estruturado,
uma vez que tem uma nica sada, mesmo quando vrios comandos exit
forem utilizados. A implementao dos comandos loop e exit idntica do
comando goto, ficando a diferena por conta das restries em seu uso.
Cada comando de repetio controlado logicamente, pode ser simulado
por outros comandos, tambm, controlados logicamente. Os comandos de
repetio controlados logicamente so mais completos que os comandos de
repetio controlados por contadores. Isto significa que qualquer comando
de repetio controlado por contadores pode ser simulado por um comando
controlado logicamente, mas a recproca no verdadeira. O exemplo a
seguir mostra como um comando de repetio controlado logicamente
simulado por outros.
Exemplo 3.5. A tabela a seguir apresenta uma implementao de um
loop e trs simulaes deste mesmo loop utilizando instrues de iterao do
tipo repeat, while e goto.

80 unidade 3
loop repeat
c1; c1;
if e then fim := e;
exit; if not fim then
c2;e c2;untilL fim;
end;
c1; ini:
while not e do c1;
begin if e then
c2; goto fim;
c1; c2;
end; goto ini;
fim:

Em Ada, a forma mais geral exit r when e; especifica a condio


e para que o comando loop de rtulo r tenha sua execuo interrompida.
A forma mais simples do comando simplesmente exit; e especifica a
interrupo do loop mais interno, de forma incondicional. Embora no oferea
um comando com as propriedades dos comandos loop de Ada ou Modula-2,
C oferece o comando break, j visto anteriormente, e que tambm permite a
sada imediata de um ponto qualquer dentro de um dos diversos comandos
de repetio.

Controle do fluxo em nvel de subprogramas

Este o terceiro nvel em que acontece o controle da execuo dos


programas. Os subprogramas representam a abstrao de processos, que
um dos dois tipos de abstrao em que as linguagens de programao se
baseiam. O outro tipo de abstrao se relaciona aos dados, de onde surgiu a
programao orientada a objetos, um tema a ser tratado na prxima unidade.
Um subprograma consiste em um conjunto de instrues que so
tratadas como uma unidade nica e pode ser chamado em vrias partes
de um programa, economizando tempo de programao e tornando os
programas menores e mais fceis de serem codificados. Os subprogramas
podem ser funes ou procedimentos. Uma funo representa uma abstrao
de uma funo matemtica e, como tal, a sua chamada sempre produz um
resultado. J os procedimentos representam a abstrao de um comando e

Controle de Fluxo 81
a sua execuo no produz um resultado, na grande maioria das linguagens
de programao.

Fundamentao dos subprogramas

Os subprogramas que sero tratados neste estudo tm algumas


caractersticas comuns a todos. So elas:
Cada subprograma tem um nico ponto de entrada.
Na execuo de um subprograma, a unidade chamadora
suspensa, ficando ativo somente o subprograma chamado.
Aps a execuo de um subprograma, o controle sempre retorna
para a unidade chamadora, exatamente no ponto seguinte ao
ponto em que foi feita a suspenso.

Algumas linguagens, por exemplo, Fortran, podem ter mltiplas


entradas, no entanto, esta deciso de seus projetistas no representa
diferenas de capacidade e de anlise.

Definies iniciais

Um subprograma constitudo de alguns componentes que devem


ser definidos, para que possam ser reconhecidos nas diversas linguagens.
So eles:
Definio. A definio de um subprograma envolve uma interface
para comunicao entre o programa e o subprograma, sendo esta
comunicao feita atravs de parmetros de entrada e de retorno,
que so variveis utilizadas apenas para este fim.
Chamada. Uma chamada a um subprograma uma solicitao
explcita para que o subprograma seja executado. Diz-se que
um subprograma est ativo se ele foi chamado, foi iniciada sua
execuo, mas ainda no foi concluda.
Perfil. O perfil de parmetros em um subprograma se relaciona
com o nmero, a ordem e os tipos dos parmetros formais.
Protocolo. O protocolo de um subprograma se refere ao perfil
mais o tipo do retorno, se for uma funo. Pode existir, ou no.
Cabealho. O cabealho de um subprograma constitudo
de uma indicao sobre o tipo do subprograma, normalmente,

82 unidade 3
indicado por uma palavra especial da linguagem, do nome do
subprograma e do protocolo, se existir.

Os parmetros dos subprogramas

Existem duas formas com as quais os subprogramas se comunicam


com o programa principal ou com outros subprogramas: por acesso direto
a variveis no locais declaradas em outros subprogramas, mas que sejam
visveis no local, ou pela passagem de parmetros. O acesso a variveis
no locais de forma descontrolada pode comprometer a confiabilidade do
sistema, porque pode acontecer que alguns acessos no sejam desejveis.
Os parmetros no cabealho de um subprograma so chamados de
parmetros formais tambm conhecidos como variveis fictcias.
As chamadas aos subprogramas incluem o nome do subprograma e
uma lista de valores conhecidos como parmetros reais que so vinculados
aos parmetros formais.
Na grande maioria das linguagens, nas chamadas a subprogramas
deve existir uma correspondncia biunvoca entre os parmetros formais e
os parmetros reais, no que se refere ordem em que os parmetros reais
so colocados. Neste caso, o primeiro parmetro real deve corresponder ao
primeiro parmetro formal e assim por diante. Neste caso, estes parmetros
so ditos posicionais. Se a lista de parmetros for muito grande fcil se
cometer um erro na ordem dos parmetros.
Para evitar este tipo de erro, algumas linguagens permitem os
parmetros de palavra-chave, onde cada parmetro formal se vincula a um
parmetro real. Este tipo de parmetro permite que a ordem dos parmetros
reais seja alterada. Por exemplo, a linguagem Ada permite a seguinte
declarao
Somador (comprimento => meu_comprimento,
vetor => meu_vetor,
soma => minha_soma);

As linguagens C++, Fortran 90 e Ada permitem que os parmetros


formais tenham valores padro. Um valor padro usado se nenhum
parmetro real for passado ao parmetro formal na chamada ao subprograma.
Por exemplo, o cabealho a seguir, em Ada:

Controle de Fluxo 83
function calc_pagamento (renda : float;
isenes : integer := 1;
tarifa_imposto : float) : return float;

O parmetro isenes pode estar ausente em uma chamada a calc_


pagamento. Neste caso, o valor 1 utilizado para ele.
A linguagem C++ no permite a declarao de parmetros de palavra-
chave, mas permite valores padro, s que com regras distintas, onde os
parmetros padro devem aparecer por ltimo, porque os parmetros so
associados posicionalmente. Uma vez que um parmetro padro seja omitido
em uma chamada, todos os parmetros formais restantes tm valores padro.

Mecanismos de passagem de parmetros

Diversos mecanismos de passagem de parmetros tem sido definidos


e implementados, de acordo com critrios de projeto ou de implementao de
cada linguagem. Vamos fazer aqui uma exposio geral desses mecanismos,
e discutir finalidades, forma de implementao, vantagens e desvantagens
de cada um.
Chamaremos, aqui, de parmetros, as variveis utilizadas na
declarao de unidades de programa com a finalidade especfica de fazer
referncia a objetos externos; os argumentos, associados aos parmetros
durante a chamada. Evitamos assim, os nomes parmetro formal e parmetro
real (ou atual) que, alm de no concordarem com o uso normal em
matemtica, se prestam confuso. Observamos que um argumento s faz
sentido no ambiente de execuo do procedimento chamador (a unidade de
programa que efetua a chamada), da mesma forma que s faz sentido o
parmetro no ambiente de execuo do procedimento chamado. A passagem
de parmetros visa exatamente permitir a referncia a valores da unidade
chamadora, no ambiente da unidade chamada.

Passagem por referncia

Este o mecanismo mais simples de passagem de parmetros: o


procedimento chamado tem acesso, atravs dos parmetros, aos prprios
argumentos. Para isso, o parmetro recebe como valor o endereo do
argumento, e, o procedimento chamado pode ler ou alterar o valor do

84 unidade 3
argumento, atravs de seu endereo. Em linguagens com outras formas
alternativas de passagem de parmetros, pode-se restringir a passagem
de expresses por referncia. Por exemplo, em Pascal, no podem ser
passadas por referncia expresses que no so variveis, e essa restrio
enfatizada pelo uso da palavra reservada var, que indica a passagem por
referncia apenas de variveis.
Casos em que no existe uma forma alternativa de passagem
de parmetros aceitam-se como argumentos passados por referncia,
expresses que no so variveis, e, em particular, valores constantes.
Como no faz sentido alterar o valor de tais argumentos, a maioria das
implementaes protege o argumento contra a alterao de valor, atravs
de sua duplicao: o parmetro recebe apenas o endereo de uma varivel
temporria, cujo valor inicial aquele obtido pela avaliao da expresso
(efetivamente uma cpia do valor, no caso de uma constante) e pode ser
alterado sem problemas. Em particular, a alterao inadvertida do valor de
uma constante traria efeitos imprevisveis para o restante da execuo do
programa.

Passagem por valor

No caso da passagem por valor, apenas o valor do argumento se torna


disponvel, e o parmetro , de fato, uma varivel local ao procedimento, que,
por ocasio da chamada, recebe, como valor inicial, o valor do argumento
j calculado no ambiente do chamador. Nenhuma ao tomada para a
devoluo de qualquer valor ao chamador. O parmetro uma varivel local,
e no h, em princpio, nenhuma proibio da alterao de seu valor.
Normalmente, a passagem por valor no deve ser a nica disponvel,
uma vez que no prev a volta de resultados para a unidade chamadora. Em
algumas linguagens (C, Algol-68), possvel passar por valor uma referncia
(endereo) do argumento. Neste caso, mesmo que o endereo se mantenha
inalterado, o contedo do endereo pode ser alterado. Em outras linguagens,
a passagem por valor aparece combinada com a passagem por resultado,
que veremos a seguir. O Exemplo 3.6 mostra como em C a passagem por
valor do endereo de uma varivel permite a emulao de uma passagem
por referncia.

Controle de Fluxo 85
Exemplo 3.6. Seja o seguinte programa em C.
void incr(int *x; int delta) -- x referncia a inteiro
{
*x += delta; -- contedo de x incrementado
}
int y=15;
int cinco=5;
... -- aqui, y = 15
incr( &y, cinco ); -- argumento o endereo de y
... -- aqui, y = 20

Passagem por resultado

De certa forma simtrica anterior, a passagem por resultado


caracteriza o parmetro como uma varivel local, cujo valor final, no instante
em que o procedimento se prepara para retornar o controle da execuo ao
chamador, passado para o argumento. O argumento, neste caso, deve ser
uma varivel. Este mecanismo semelhante quele utilizado por uma funo
para devolver seu resultado; a diferena consiste na notao, e o parmetro
pode no ter nome: uma varivel temporria com a finalidade de receber
este valor, e permitir sua transmisso para a unidade chamadora. Em algumas
linguagens, o prprio nome da unidade usado para esse parmetro, em
outras, indica-se o valor a ser devolvido atravs de uma palavra chave, tal
como result ou return.

Passagem por valor-resultado

Neste caso, a passagem por valor aparece combinada com a


passagem por resultado: o parmetro entendido como uma varivel local
inicializada com o valor do argumento, e cujo valor final passado ao
argumento, no trmino da execuo. Como na passagem por referncia,
possvel consultar e alterar o valor de uma varivel, mas, as duas formas no
so equivalentes, como veremos na comparao entre formas de passagem
de parmetros, mais abaixo.

86 unidade 3
Passagem por nome

Esta forma de passagem considera um aspecto ainda no examinado:


no s o valor de um argumento pode se alterar durante a execuo da
unidade chamada, mas o prprio argumento pode se modificar. Por exemplo,
se o argumento a componente de array y[i+1,j], e as variveis i e j tm seus
valores alterados durante a execuo, a varivel cujo nome y[i+1,j] tambm
se modifica, e pode, em princpio, ser qualquer uma das componentes do
array y.
Na passagem por nome, o programador entende o parmetro como
sendo o argumento que tem aquele nome, em cada instante da execuo, e
no o argumento que tinha aquele nome por ocasio da chamada. Assim, o
parmetro reflete as alteraes de valor do argumento, e as alteraes do
prprio argumento, quando seu nome (fixo) passa a descrever outra varivel.
Para o programador, tudo se passa como se o cdigo (fonte) do
procedimento chamado fosse copiado, substituindo-se cada uso de um
parmetro pelo nome do argumento correspondente. Naturalmente, essa
regra da cpia no pode, em geral, ser diretamente aplicada, sem levar em
conta a diferena dos ambientes de execuo: o mesmo nome pode significar
coisas distintas em distintos ambientes, e o clculo do valor do argumento s
pode ser feito no ambiente do chamador.
A unidade chamadora no pode fornecer, no momento da chamada, o
valor do argumento ou seu endereo, uma vez que isto no seria adequado.
De acordo com a implementao mais tpica, a unidade chamadora fornece a
forma de calcular os argumentos correspondentes aos nomes dados, atravs
de trechos de cdigo construdos com essa finalidade. Esses trechos (thunks)
podem ser vistos como procedimentos sem parmetros, que calculam o valor
ou o endereo de um argumento, conforme apropriado; cada thunk ativado
quando necessrio pela unidade chamada, mas sempre executado no
ambiente de execuo da unidade chamadora.
O Exemplo 3.7 mostra como a passagem por nome pode ser utilizada,
de forma difcil de simular nas outras formas de passagem de parmetros.
A um programador no acostumado com a passagem por nome, dificilmente
ocorreria a ideia de dar a todas as componentes de um vetor v o valor zero,
chamando um procedimento como o procedimento zero, cujo nico argumento
uma componente genrica v[i] do vetor v.
Nenhuma das outras formas de passagem de parmetros permitiria o

Controle de Fluxo 87
acesso a uma componente genrica de v[i]: por valor, seria passado o valor
de v[i], para o valor inicial de i; por referncia, seria passado o endereo
de v[i], tambm para o valor inicial de i. No caso da passagem por nome, o
que efetivamente passado a forma de clculo do endereo da i-sima
componente de v, v[i].

Exemplo 3.7. Seja o seguinte fragmento de programa em Pascal.


var
i:integer;
v:array[1..100] of integer;
procedure zera(j:integer);
begin
for i:=1 to 100 do
j:=0;
end;
...
zera(v[i]);

Comparao. As diversas formas de passagem de parmetros


correspondem, como vimos, a diferentes formas de implementao, e
conduzem a diferentes resultados, que, entretanto, na maioria dos casos,
no oferecem surpresas. Por exemplo, podemos distinguir entre passagem
por referncia e passagem por valor/resultado com o procedimento incr2 do
Exemplo 3.8.

Exemplo 3.8. Seja o seguinte fragmento de programa em Pascal.


procedure incr2(x,y:integer);
begin
x:=x+1;
y:=y+1;
end;
...
z:=0;
incr2(z,z);
...

Se for usada a passagem de parmetro por referncia, o valor de z

88 unidade 3
aps a chamada ser 2; se for usada a passagem de parmetros por valor/
resultado, o valor ser 1.
A passagem por referncia foi uma das primeiras metodologias de
passagem de parmetros a ser utilizada, e a forma oferecida por Fortran.
Em Algol-60, a passagem por nome default mas tambm oferecida a
passagem por valor, para acelerar a execuo dos programas em que uma
longa sequncia de chamadas (por exemplo, de um procedimento recursivo)
implicaria num nmero grande de chamadas de thunks, com prejuzo da
velocidade. Pascal, em virtude da preocupao com simplicidade que presidiu
ao seu projeto, oferece as duas maneiras mais simples de passagem de
parmetros: por valor (default) e por referncia (indicada por var). O caso
da linguagem Ada interessante: os parmetros podem ser declarados de
trs modos: in, out, in out, que aparentemente correspondem passagem
por valor, resultado, e valor-resultado. O manual da linguagem, entretanto,
abre a possibilidade de que o modo in out seja implementado por referncia,
e adverte o programador que um programa cujo funcionamento correto
dependa da forma de implementao um programa Ada errneo. Segundo o
mesmo manual, um programa errneo um programa incorreto, mas nenhum
compilador de Ada precisa indicar este fato. Por exemplo, um programa Ada
semelhante ao do Exemplo 3.9 seria errneo. O Exemplo 21 mostra como
simular passagem por nome atravs de outras formas.

Exemplo 3.9. Suponhamos que se deseja calcular xi para m i n,


atravs de uma funo soma, que deve receber como parmetros i, m, n, xi:
soma(i, m, n, xi). Com a passagem por nome, podemos escrever:
integer function soma(i, m, n, x);
integer i,m,n,x;
begin
integer s;
s:=0;
for i:=m to n do s:=s+x;
soma:=s;
end;

Por exemplo, para calcular A[i, j], 1 i m, 1 j n deveramos


chamar soma (i,1,m,soma(j,1,n,A[i,j])).
Se quisermos implementar o mesmo problema em Pascal, teremos

Controle de Fluxo 89
que definir uma funo que calcule o valor de xi, e passe essa funo como
argumento para a funo soma.

function soma(var i, m, n : integer; function x : integer) : integer;


var s:integer;
begin
s:=0;
for i:=m to n do s:=s+x;
soma:=s;
end;

Neste caso, para calcular o duplo somatrio, teramos que definir uma
funo Aij, que calcularia o valor da componente i,j de A.
soma(i,1,m,soma(j,1,n,Aij)
A funo Aij deve apenas atrasar o clculo de A[i,j], esperando que i
e j tenham atingido os valores apropriados:
function Aij:integer;
begin
Aij:=A[i,j]
end;

Note que no h necessidade de alterar a forma de passagem dos


demais parmetros de soma (i, j, m), porque, tratando-se de variveis simples,
os efeitos da passagem desses parmetros por nome e por referncia se
equivalem.

Subprogramas sobrecarregados

Um subprograma sobrecarregado se ele tiver vrias implementaes.


Isto significa que o mesmo subprograma atua sobre tipos de dados distintos,
implementando algoritmos tambm distintos. Por exemplo, o operador de
multiplicao * em C utilizado para multiplicar dois nmeros reais e tambm
para multiplicar dois nmeros inteiros. A multiplicao de inteiros bem
diferente da multiplicao de nmeros reais, porque as representaes em
bits de nmeros reais so diferentes da representao de nmeros inteiros,
e os circuitos dos computadores dedicados a estas operaes so distintos.
Alguns projetistas de linguagens argumentam que a sobrecarga no

90 unidade 3
aumenta o poder de expressividade de uma linguagem, exatamente porque
implementa algoritmos distintos. Se eles so distintos, podem ter nomes
tambm distintos.
No entanto, muitos projetistas argumentam que alguma forma de
sobrecarga deve existir pelo menos para operaes que tenham alguma
coisa em comum, como a multiplicao de nmeros, e muitas linguagens
adotam esta tcnica.
Por exemplo, C++, Java e Ada incluem subprogramas sobrecarregados
pr-definidos e os programadores tambm tm permisso para escrever
mltiplas verses de subprogramas com o mesmo nome nessas linguagens.

Subprogramas genricos

A reutilizao de software tem representado uma tcnica de


programao importante, notadamente, na implementao de grandes
sistemas, em que a programao feita por grupos ou times de profissionais.
A Engenharia de Software tem se preocupado com o gerenciamento destes
grupos e times, empregando vrias tcnicas para isto.
Neste caso, a reutilizao pode ser incrementada pela construo de
subprogramas que possam ser utilizados em mais de um tipo de dados, mas,
fazendo exatamente a mesma implementao. Subprogramas genricos
ou polimrficos aumentam a produtividade do software pelo fato de
poderem ser aplicados a vrios tipos de dados. Isto significa que o mesmo
subprograma pode ser aplicado a vrios tipos de dados. Os subprogramas
sobrecarregados apresentam uma espcie particular de polimorfismo
chamado de polimorfismo ad hoc.

Corrotinas

Uma corrotina um tipo especial de subprograma em que no existe


a reao mestre-escravo entre o chamador e o chamado. O modelo de
controle de corrotinas, frequentemente chamado de modelo de controle
simtrico. Este modelo de controle foi implementado pela primeira vez em
Simula 67.
Ao contrrio dos subprogramas comuns, as corrotinas tm vrios
pontos de entrada que so controlados pelas prprias corrotinas, e tm
meios de manter sua histria entre as ativaes. As execues das corrotinas

Controle de Fluxo 91
normalmente tm incio em pontos distintos do incio, sendo este, o motivo
pelo qual se chama de retomada da rotina, em vez de chamada.
Tipicamente, as corrotinas so criadas em uma aplicao por uma
unidade de programa chamada de unidade mestra, que no uma corrotina.
Um exemplo clssico que simula a execuo de corrotinas um jogo
de cartas em que participam quatro jogadores, utilizando a mesma estratgia
de jogo. O programa mestre inicia a simulao, retomando uma das corrotinas
jogadoras, que, depois de haver jogado sua vez, poderia retomar a seguinte
e assim por diante at o jogo terminar.
A Figura 3.1 a seguir, mostra graficamente uma possvel sequncia
de execuo de duas corrotinas A e B. Na figura pode-se observar os vrios
pontos de entrada e de sada que as corrotinas tm. A execuo de programas
em tempo compartilhado, onde, para cada processo destinado um time
slice, d-se atravs de corrotinas. Uma vez que, cada processo tem de ficar
suspenso por algum perodo e tem de retornar ao ponto em que foi suspenso
para continuar a sua execuo, quando for dado a ele um novo time slice.
Figura 3.1. Esquema de execuo de duas corrotinas.

92 unidade 3
Exerccio

1. Que so valor-l e valor-r das variveis?

2. Que um apelido no contexto das linguagens de programao?

3. Que so as variveis estticas, no contexto das linguagens de programao?

4. Que so as variveis dinmicas na pilha, no contexto das linguagens de


programao?

5. Que so as variveis dinmicas no heap explcitas, no contexto das


linguagens de programao?

6. Que so as variveis dinmicas no heap implcitas, no contexto das


linguagens de programao?

7. Que coero de tipos?

8. Quais os tipos de iterao utilizados pelas Linguagens de Programao?


Qual a mais genrica?

9. Qual a diferena entre o comando for de Java e de C++?

10. Quais os principais mtodos de passagem de parmetros utilizados pelas


linguagens de programao em seus subprogramas?

11. Qual a diferena entre um procedimento e uma funo nas linguagens de


programao?

12. O que so as corrotinas e quais as suas diferenas com relao aos


subprogramas?

13. Qual a diferena entre sobrecarga e polimorfismo?

Controle de Fluxo 93
SAIBA MAIS

Existem muitos bons textos sobre este tema. Alguns deles esto listados
em Referncias e colocados ao final desta Unidade. A nosso ver, um livro
importante o livro de David Watt, onde ele reala a ligao entre a Matemtica
e a Cincia da Computao em termos da teoria dos conjuntos e dos tipos de
dados. Outros esto na Internet disposio. Estes esto listados a seguir.

94 unidade 3
UNIDADE 4
Abstrao de Dados

Resumindo
O objetivo principal desta unidade apresentar os principais conceitos envolvidos nas abstraes
de dados e como eles so utilizados nas linguagens de programao. Inicialmente, ser vista uma
anlise dos tipos abstratos de dados e como eles podem ser utilizados para resolver o problema
da crise do software dos anos 80. Em um segundo momento, a anlise se estende s linguagens
de programao projetadas para incorporar as caractersticas dos tipos abstratos de dados,
conhecidas como linguagens orientadas a objetos. Os objetos sero vistos como tipos abstratos de
dados que incorporam mais uma caracterstica que herana. A unidade termina com uma anlise
das principais linguagens de programao orientadas a objetos. A forma de apresentao utilizada
de acordo com o exigido para o ensino a distncia, ou seja, tendo em vista sempre esta nova
modalidade de ensino
abstrao de dados

Introduo

O termo Programao Orientada a Objetos foi criado por Alan Kay,


autor da linguagem de programao Smalltalk. Mas mesmo antes da criao
do Smalltalk, algumas das ideias da POO j eram aplicadas, sendo que a
primeira linguagem a realmente utilizar estas ideias foi a linguagem Simula
67, criada por Ole Johan Dahl e Kristen Nygaard em 1967. Este paradigma
de programao j bastante antigo, mas apenas ultimamente vem sendo
aceito, realmente, nas grandes empresas de desenvolvimento de software.
Alguns exemplos de linguagens modernas, utilizadas por grandes empresas
em todo o mundo, que adotaram essas ideias: Java, C#, C++, Object Pascal
(Delphi), Ruby, Python e Lisp.
A maioria delas adota as ideias, parcialmente, dando espao para
o antigo modelo procedural de programao, como acontece no C++, por
exemplo, onde temos a possibilidade de usar POO, mas a linguagem no
fora o programador a adotar este paradigma de programao, sendo ainda
possvel programar da forma procedural tradicional. Este tipo de linguagem
segue a ideia de utilizar uma linguagem previamente existente como base e
adicionar novas funcionalidades a ela.
Outras so mais puras, sendo construdas do zero, focando-se
sempre nas ideias por trs da orientao a objetos, como o caso das
linguagens Smalltalk, Eiffel, Self e IO, onde TUDO orientado a objetos.

O conceito de abstrao

Uma abstrao significa uma visualizao ou a representao de uma


entidade, incluindo apenas os atributos que sejam realmente importantes

Abstrao de Dados 97
em um contexto particular. Isto permite que se construam grupos destas
entidades, que guardem entre si, atributos comuns. Estes atributos comuns
podem ser abstrados, e, dentro de cada grupo, somente os atributos que
distinguem os elementos individuais precisam ser considerados. Isto permite
que os elementos do grupo sejam simplificados. A abstrao uma arma
contra a complexidade na programao, por simplificar e muito este processo.
Consideram-se dois tipos de abstrao nas linguagens atuais: a
abstrao de processos e a abstrao de dados.

A abstrao de processos

Este conceito mais antigo que o de dados e mesmo as linguagens


mais antigas o incorporam. Os subprogramas so abstraes de processos,
porque permitem que um processo seja executado sem a necessidade de
especific-lo em cada ponto de chamada. Por exemplo, quando se precisa
ordenar um vetor em uma execuo de um programa, constri-se um
subprograma para realizar esta tarefa, imaginando-se que outros vetores
tambm necessitem ser ordenados futuramente no programa. Neste caso,
apenas o subprograma chamado tendo um novo vetor como parmetro,
no sendo necessrio, novamente, escrever todo o cdigo para fazer esta
ordenao. A abstrao de processos permite que programas grandes
possam ser lidos e entendidos mais facilmente. A principal motivao para a
abstrao de dados a mesma da abstrao de processos. Busca resolver o
problema da complexidade dos grandes programas.
O conceito de abstrao de dados constitui o objetivo principal desta
unidade e ser visto em todo o decorrer deste estudo. Para entender de
forma plena as suas funcionalidades necessrio, antes, conhecer alguns
outros conceitos importantes que so pr-requisitos para o domnio desta
metodologia de programao.

O conceito de encapsulamento

J foi mencionada em outras unidades a existncia da programao


simples, conhecida como programming in the small e a programao mais
complexa, denotada como programming in the large. Nesta ltima, quando os
programas representam algumas centenas de milhares de linhas de cdigo,
surgem alguns problemas de ordem prtica.

98 unidade 4
O primeiro deles se refere dificuldade que o programador ter
na administrao destes sistemas de forma coerente e confivel, sendo
necessria uma organizao em mdulos, que so grupos de subprogramas
e dados que estejam logicamente relacionados.
O segundo problema diz respeito recompilao, aps alguma
modificao em alguma parte do programa. Nos programas pequenos este
problema praticamente inexistente, mas, em um sistema grande, o custo de
recompilao se torna significativo. necessrio encontrar formas de evitar
que as unidades que no foram modificadas sejam tambm recompiladas.
Isto pode ser conseguido organizando-se os programas em colees de
subprogramas e de dados, em que cada uma destas colees possam ser
compiladas, sem a necessidade de que as outras tambm sejam. Esta
coleo conhecida como unidade de compilao.
O encapsulamento um agrupamento de subprogramas e dos dados
que eles manipulam. Ele constitui um sistema abstrado e uma organizao
lgica para uma coleo de computaes relacionadas. Ele resolve os dois
problemas elencados anteriormente.
Os encapsulamentos so, muitas vezes, incorporados a bibliotecas e
colocados disposio para serem reutilizados em programas que no foram
projetados para utilizar estas bibliotecas.
Em muitas linguagens de programao do tipo Algol, os programas
podem ser aninhados, como, por exemplo, Pascal. Tal mtodo de organizao
de programas utilizando regas de escopo esttico tem sido muito condenado,
exatamente pelo fato de que os subprogramas no podem ser recompilados
separadamente. Ou seja, os subprogramas aninhados no criam boas
construes de encapsulamentos.
Na linguagem C, uma coleo de funes e definies de dados
relacionadas pode ser colocada em um arquivo, que pode ser compilado
de forma independente. No entanto, as definies de dados em arquivos
diferentes no so verificadas. Isto significa que os arquivos em C no criam
encapsulamentos seguros.
Fortran 90 e Ada permitem que colees de subprogramas de tipos
e de dados sejam agrupadas em unidades que podem ser compiladas,
separadamente, de forma que as informaes de interface sejam salvas
pelo compilador e usadas na verificao de tipos, quando usadas por outra
unidade. Essas unidades fazem encapsulamentos perfeitos.

Abstrao de Dados 99
Tipos de dados abstratos definidos pelo usurio

Formalmente, um tipo de dado abstrato definido pelo usurio um


tipo de dado que satisfaz as duas seguintes condies:
A representao ou a definio do tipo e as operaes sobre
instncias do tipo esto contidas em uma nica unidade sinttica.
Alm disso, outras unidades de programa tm permisso para
criar variveis do tipo definido.
A representao de uma instncia do tipo no visvel pelas
unidades de programa que usam o tipo, de modo que as nicas
operaes diretas possveis sobre essas instncias so aquelas
oferecidas na definio do tipo.

As unidades de programa que usam um tipo de dado abstrato


especfico so chamadas clientes desse tipo.
As vantagens de empacotar a representao e as operaes em uma
mesma unidade sinttica so as mesmas j vistas para o encapsulamento.
A principal delas que os clientes no so capazes de ver os detalhes da
representao e seu cdigo no pode depender dessa representao. Em
consequncia disso, as representaes podem ser modificadas a qualquer
instante sem exigir modificaes nos clientes. Alm do mais, o fato dos
clientes no poderem modificar as representaes, resulta em programas
mais confiveis, aumentando a integridade das instncias desses tipos de
dados.
Para construir um tipo abstrato de dado necessrio, antes de tudo,
definir que operaes o tipo de dado vai oferecer aos clientes deste tipo. Por
exemplo, para definir um tipo abstrato pilha necessrio definir as operaes
mostradas na tabela a seguir. Estas operaes so as mais comuns em uma
estrutura deste tipo. Os nomes esto em ingls por ser o uso comum e a
traduo pode gerar dvidas por parte dos clientes.

100 unidade 4
Tabela 4 1. Principais operaes de uma pilha.
create(stack) Cria e possivelmente inicializa uma pilha
destroy(stack) Desaloca o armazenamento da pilha
empty(stack) Uma funo que verifica se a pilha est vazia ou
no
push(stack, element) Coloca um elemento na pilha
pop(stack) Remove o elemento do topo da pilha
top(stack) Retorna uma cpia do elemento do topo da pilha

Tipos de dados abstratos em Ada

As construes de encapsulamento em Ada so chamadas de


pacotes, que so compostos de duas partes: a especificao do pacote onde
feita definio da interface do encapsulamento e o corpo do pacote, onde
so feitas as implementaes das entidades nomeadas na especificao.
No obrigatria a presena do corpo do pacote nos tipos abstratos de Ada,
se ele no for necessrio. Por exemplo, pacotes que encapsulam apenas
dados e constantes no precisam ter um corpo.
A especificao de um pacote e o seu corpo tm o mesmo nome.
O corpo de um pacote identificado pela palavra reservado package co
cabealho do corpo. A especificao e o corpo de um pacote podem ser
compilados separadamente, desde que a especificao seja compilada antes
do corpo.
Exemplo 4.1. Vamos mostrar uma definio de uma pilha como
um tipo abstrato de dado em Ada. As operaes para o tipo pilha so as
mostradas na Tabela 4.1.
package Stack_Pack is -- as entidades visveis aos clientes
type Stack_Type is limited private;
Max_Size : constant := 100;
function Empty (Stk : in Stack_Type) return Boolean;
procedure Push(Stk : in out Stack_Type;
Element : in Integer);
procedure Pop (Stk : in out Stack_Type);
function Top (Stk : in Stack_Type) return Integer;
private
type List_Type is array (1 .. Max_Size) of Integer;
type Stack_Type is

Abstrao de Dados 101


record
List : List_Type;
Topsub : Integer range 0 . . Max_Size := 0;
end record;
end Stack_Pack;
Deve ser observado que nenhuma operao de criao ou de
destruio foi includa porque elas no so necessrias. O corpo do pacote
Stack_Pack definido da seguinte forma:
with Ada.Text_IO; use Ada.TExt_IO;
package package Stack_Pack is
function Empty(Stk : in Stack_Type) return Boolean is
begin
return Stk.Topsum = 0;
end Empty;
procedure Push(Stk : in out Stack_Type;
Element : in Integer) is
begin
If Stk.Topsum >= Max_Size
then Put_Line(ERROR Stack overflow);
else
Stk.Topsum := Stk_Topsub + 1;
Stk_List(Topsub) := Element;
end if;
end Push;

procedure Pop(Stk : in out Stack_Type) is


begin
If Stk.Topsub = 0
then Put_Line(ERROR Stack underflow);
else Stk.Topsub := Stl.Topsub 1;
end if;
end Pop;

function Top(Stk : in Stack_Type) return Integer is


begin
If Stk.Topsub = 0
then Put_line(ERROR Stack is empty);

102 unidade 4
else return Stk.List(Stk.Topsub);
end if;
end Top;
end Stack_pack;

O procedimento Use_Stacks, a seguir, um cliente do pacote Stack_


pack. Ele ilustra como o pacote pode ser usado.
with Stack_Pack, Ada.Text_IO;
use Stack_Pack, Ada.Text_IO;
procedure Use_Stacks is
Topone : Integer;
Stack : Stack_Type; cria uma instncia de Stack_Type
begin
Push(Stack, 19);
Push(Stack, 30);
Topone := Top(Stack);
Pop(Stack);
...
end Use_Stacks;

Tipos abstratos de dados em C++

A linguagem C++ foi criada pela adio de suporte programao


orientada a objetos. Ada oferece encapsulamento para simular tipos de dados
abstratos, atravs dos pacotes, enquanto C++ oferece as classes que so
tipos. Em C++ as variveis so declaradas como instncias de uma classe,
tornando-as mais parecidas com os tipos.
As classes em C++ podem conter entidades ocultas, declaradas
pela clusula private, e tambm entidades pblicas declaradas pela clusula
public.
Em C++ dispe-se de uma funo constructor na definio de uma
classe, usada para inicializar dados dinmicos no heap e tambm de uma
funo destructor, chamada, implicitamente, para encerrar o tempo de vida
de uma instncia de uma classe, usada com o sinal ~.
Exemplo 4.2. O mesmo tipo abstrato pilha, implementado em Ada no
Exemplo 4.1, ser aqui mostrada sua implementao em C++, para que o
leitor possa fazer uma comparao entre as duas implementaes.

Abstrao de Dados 103


#include <iostream.h>
class stack {
private:
int *stackPtr;
int max_Size;
int topPtr;
public:
stack( ) {
stackPtr = new int [100];
max_Size = 99;
topPtr = -1;
}
~stack( ) {delete [ ] stackPtr;}; //** funo destrutora
void push (int numbar) {
If (topPtr = = Max_len)
cerr << Error in push-stack is full\n;
else stackPtr[++topPtr] = number;
}
void pop( ) {
If (topPtr = = -1)
cerr << Error in pop-stack is empty\n;
else topPtr- -;
}
int top( ) {return (stackPtr[topPtr]);}
int emptry( ) {return (topPtr = = -1);}
}

Para utilizar este tipo de dado em C++, o programa a seguir mostra


uma possibilidade.
void main( ) {
int topOne;
stack stk;
stk.push (19);
stk.push (30);
topOne = stk.top( );
stk.pop(.):

104 unidade 4
...
}

Tipos abstratos de dados em Java

O suporte da linguagem Java para os tipos abstratos de dados


similar ao de C++, com apenas algumas diferenas. Todos os tipos de dados
abstratos definidos pelo usurio em Java so classes, j que Java no inclui
structs, e todas as instncias so alocadas no heap e so acessadas via
variveis do tipo referncia. Outra diferena que os mtodos de Java s
podem ser definidos em classes. Assim, um tipo de dado abstrato em Java
declarado e definido em uma mesma unidade sinttica.
Em vez de ter as clusulas privadas e pblicas nas definies de
classes, em Java, os acessos podem ser incorporados aos mtodos e nas
definies de variveis.
Exemplo 4.3. O mesmo tipo de dado pilha, j visto anteriormente,
implementado em Ada e em C++, ser aqui mostrada sua implementao em
Java.
import Java.io.*;
class StackClass {
private int [ ] stackRef;
private int maxLen, topIndex;
public StackClass( ) { // Um construtor
stackRef = new int [100[;
maxLen = 99;
topIndex = -1;
}
public void push (int number) {
If (topIndex = = maxLen)
System.out.println(Error in pop-stack is empty);
else - - topIndex;
}
public int top( ) {return (stackRef[topIndex]);}
public boolean empty( ) {return (topIndex = = -1);}
}
O fragmento de cdigo a seguir, em Java, mostra uma forma de
utilizao deste tipo abstrato de dado.

Abstrao de Dados 105


public class TstStack {
public static void main(String[ ] args) {
StackClass myStack = new StackClass( );
myStack.push (19);
myStack.push (30);
System.out.println(30 is: + myStack.top( ));
myStack.pop ( );
System.out.println(19 is: + myStack.top( ));
myStack.pop ( );
myStack.pop ( ); }
}

Programao orientada a objetos

A programao orientada a objetos tem sua origem em Simula 67,


mas ficou estabelecida a partir da linguagem Smalltalk, considerada por
alguns a nica linguagem verdadeiramente orientada a objetos.
A programao orientada a dados concentra-se nos tipos de dados
abstratos. Neste caso, as operaes a serem realizadas em um dado so
feitas atravs de funes ou mtodos associados a este dado. Por exemplo,
se um vetor precisa ser classificado, ele declarado como um tipo de dado
abstrato, onde a classificao do vetor feita atravs de uma funo de
classificao associada ao tipo de dado. As linguagens que suportam a
programao orientada a dados e incorporam um mecanismo de herana
e um tipo particular de vinculao dinmica, ficaram conhecidas como
linguagens orientadas a objetos.
Em POO, as classes so declaraes de objetos, que poderiam
tambm ser definidas como abstraes de objetos. Isto quer dizer que a
definio de um objeto tambm a definio da classe da qual os objetos
so instncias desta classe. Quando definimos um objeto com suas
caractersticas e funcionalidades, em verdade, o que estamos definindo
uma classe. Portanto, para um cliente, as classes so tipos abstratos de
dados que herdam.
Desta forma, antes de investigarmos outras construes das
linguagens orientadas a objetos, vamos analisar os suportes que fundamentam
a programao orientada a objetos. Vamos iniciar pelo mecanismo de herana.

106 unidade 4
Herana

Com o advento da programming in the large, os desenvolvedores de


software verificaram ser importante desenvolver sistemas que pudessem ser
reutilizados em solues de problemas semelhantes. Os tipos abstratos de
dados foram evidentemente os principais candidatos a realizar este objetivo,
devido ao encapsulamento e ao controle de acesso que eles permitiam.
No entanto, para ser utilizado como soluo para um novo problema, um
tipo de dado abstrato teria que ter alguma modificao e isto exigiria que o
programador que fosse faz-la, tivesse conhecimento de parte ou de todo o
cdigo existente. Alm disso, essas modificaes exigiriam mudanas em
todos os programas clientes.
Um segundo problema com as definies em tipos abstratos de
dados que elas so todas independentes e esto no mesmo nvel. Isto,
frequentemente, torna impossvel estruturar um programa que se ajuste ao
espao de um outro problema. Em muitos casos, os problemas exigem a
construo de estruturas com certo grau de hierarquia.
O mecanismo de herana oferece uma soluo tanto para o problema
de modificao apresentado pela reutilizao de tipos abstratos, quanto para
o problema de organizao do programa. Se um novo tipo de dado puder
herdar os dados e a funcionalidade de um tipo existente e modificar algumas
entidades existentes e acrescentar algumas prprias, a reutilizao ser
aumentada grandemente, sem exigir modificaes no tipo de dado abstrato
reutilizado.
Vamos imaginar um sistema para a Biologia, modelando o homem
como um animal. O homem tem todas as caractersticas (atributos) dos
animais e pode realizar todas as aes (mtodos) de um animal. Alm disso,
o homem tambm tem algumas outras caractersticas e aes inerentes
apenas a ele.
Para simular este contexto, vamos criar a classe Animal e a classe
SerHumano como uma subclasse da classe Animal. A subclasse SerHumano
tem todas as caractersticas e comportamentos da classe Animal e mais
algumas outras adicionais inerentes apenas ao ser humano. Neste caso, a
subclasse SerHumano herda o estado e o comportamento da classe Animal.
A classe SerHumano ser uma especializao da classe Animal. A
classe Animal a classe pai da subclasse SerHumano, e logicamente, a
classe SerHumano a classe filha da classe Animal.

Abstrao de Dados 107


Uma classe pode sempre ter vrios filhos. Uma classe pode ter apenas
um pai, como Smalltalk, o que caracteriza herana simples, no entanto, a
linguagem C++ permite que uma classe herde as caractersticas de vrias
classes, caracterizando a herana mltipla. Deve ser lembrado, no entanto,
que C++ no um bom exemplo quando se est falando sobre conceitos de
POO. C++ , na realidade, a linguagem C com uma extenso para orientao
a objetos, o que diferente de uma linguagem que foi projetada para ser
orientada a objetos, como Smalltalk.
Como outro exemplo um pouco mais prximo da nossa realidade,
vamos imaginar um sistema para um banco comercial. O banco possui
clientes que so pessoas fsicas e jurdicas.
Poderamos criar uma classe chamada Pessoa com os atributos
Nome e Idade. Em seguida, criamos duas classes que sero filhas da
classe Pessoa, chamadas PessoaFisica e PessoaJuridica. Tanto a classe
PessoaFisica como Pessoa Juridica herdam os atributos da classe Pessoa,
mas tambm, podem ter seus prprios atributos a mais. Por exemplo, a classe
PessoaFisica pode ter o atributo RG, enquanto a classe PessoaJuridica pode
ter o atributo CNPJ. Assim, os objetos da classe PessoaFisica tero como
atributos: Nome, Idade e RG, enquanto os objetos da classe PessoaJuridica
tero os atributos: Nome, Idade e CNPJ.
Com relao aos mtodos, pode-se agir de forma semelhante.
Poderamos criar alguns mtodos na classe Pessoa e mais alguns nas classes
PessoaJuridica e PessoaFisica. No final, todos os objetos teriam os mtodos
especificados na classe Pessoa, mas s os objetos do tipo PessoaJuridica
teriam os mtodos especificados dentro da classe PessoaJuridica, e objetos
do tipo PessoaFisica teriam os mtodos especificados na classe PessoaFisica.

Estados em objetos

Quando temos um objeto suas propriedades tomam valores. Por


exemplo, quando temos um carro a propriedade cor tomar um valor concreto,
como, por exemplo, preto, cinza, etc. O valor concreto de uma propriedade de
um objeto chama-se estado.
Para acessar o estado de um objeto, ver o seu valor ou atualiz-lo,
em muitas linguagens, utiliza-se o operador ponto. Por exemplo,
meuCarro.cor = amarela;
que, deve ser interpretado como, a cor do objeto meuCarro ser amarela.

108 unidade 4
Neste caso, estamos atualizando o valor do estado da propriedade do objeto
para amarela, com uma simples atribuio.

Mensagens em objetos

Uma mensagem em um objeto a ao de efetuar uma chamada


a um mtodo. Por exemplo, quando dizemos ao objeto carro para andar,
estamos lhe passando a mensagem ande.
A forma utilizada pelas linguagens para enviar mensagens aos objetos
a mesma utilizada para atualizar os estados dos objetos. Na maioria das
linguagens, utilizada a notao de ponto. Por exemplo, o comando
meuCarro.andar();
significa que estamos passando a mensagem andar() para o objeto meuCarro.
Deve-se colocar parnteses, como em qualquer chamada a uma funo,
colocando dentro deles os parmetros.
Exemplo 4.4. Seja o caso de uma locadora de vdeos com diversos
clientes. Poderamos ento criar uma classe Cliente com as seguintes
caractersticas (atributos): Nome, Data de Nascimento e Profisso.
Um cliente mais que simples dados. Ele pode realizar aes! E no
mundo da POO, aes so descritas atravs de mtodos.
Dessa forma, objetos da classe Cliente podero, por exemplo, executar
as seguintes aes (mtodos): AlugarFilme, DevolverFilme e ReservarFilme.
Note o tempo verbal empregado ao descrever os mtodos. Fica fcil
perceber que tratam-se de aes que um Cliente pode realizar.
muito importante perceber as diferenas entre Atributo e Mtodo.
No comeo, normal ficar um pouco confuso, mas tenha sempre em mente
que atributos so dados e mtodos descrevem aes que os objetos so
capazes de realizar.
Assim, nosso sistema pode ter vrios Objetos do tipo Cliente. Cada
um destes objetos possuir seu prprio nome, data de nascimento e profisso,
e todos eles podero realizar as mesmas aes (AlugarFilme, DevolverFilme
ou ReservarFilme).
De forma resumida, os objetos tm estados, representados por seus
campos, e tambm tem comportamentos, representados por seus mtodos.

Abstrao de Dados 109


Polimorfismo

Um dos conceitos mais complicados de se entender, e tambm um


dos mais importantes, o Polimorfismo. O termo originrio do grego e
significa muitas formas.
Na orientao a objetos, polimorfismo significa que um mesmo objeto,
sob certas condies, pode realizar aes diferentes ao receber uma mesma
mensagem. Isto significa que apenas olhando o cdigo fonte no possvel
saber exatamente qual ser a ao a ser tomada pelo sistema, sendo que, o
prprio sistema quem decide qual mtodo ser executado, dependendo do
contexto durante a execuo do programa. Desta forma, a mensagem fale
enviada a um objeto da classe Animal, pode ser interpretada de diferentes
formas, dependendo do objeto em questo. Para que isto ocorra, preciso
que duas condies sejam satisfeitas: exista herana de uma classe abstrata
e Casting (outras situaes tambm podem resultar em polimorfismo, mas
vamos nos centrar neste caso). Estes termos sero explicados a seguir.

Classes abstratas

Uma classe abstrata uma classe que representa uma coleo de


caractersticas presentes em vrios tipos de objetos, mas que no existe
e no pode existir isoladamente. Por exemplo, podemos criar uma classe
abstrata chamada Animal. Um Animal tem diversas caractersticas (atributos)
e pode realizar diversas aes (mtodos), mas no existe a possibilidade
de criarmos objetos do tipo Animal. O que existem so objetos das classes
Cachorro, Gato, Papagaio, etc. Essas classes estendem a classe Animal,
herdando todas as suas caractersticas, e adicionando algumas coisas
a mais. Animal s uma entidade abstrata, apenas um conjunto de
caractersticas em comum, nada mais.
Voc pode olhar para um objeto da classe Cachorro e falar isto
um animal, pois estende a classe Animal, mas voc nunca vai ver um objeto
que seja apenas da classe Animal, pois isso no existe! como eu olhar
para voc e falar voc um objeto da classe SerVivo. Essa afirmao est
correta, mas voc na verdade um objeto da classe Ser Humano, que, por
sua vez, herda todas as caractersticas da classe SerVivo (que, por sua
vez, uma classe abstrata, j que no podemos criar algo que seja apenas
classificado como SerVivo, sempre vamos classific-lo de forma menos
genrica). Resumindo: uma classe abstrata um conjunto de informaes a

110 unidade 4
respeito de uma coleo de outras classes. Uma classe abstrata sozinha
completamente intil, j que no podemos instanciar um objeto desta classe,
podemos apenas instanciar objetos de classes que estendem a classe
abstrata inicial. Ela serve apenas para simplificar o sistema, juntando em um
nico lugar diversas caractersticas que so comuns a um grupo de classes.
No esquea disso: voc nunca vai poder criar um objeto do tipo de
uma classe abstrata. Sempre crie objetos das classes que estendem a classe
abstrata.

Casting em POO

O termo Casting utilizado quando ns foramos o sistema a ver


um objeto como sendo de um determinado tipo, que no o seu tipo original.
Suponhamos a situao mostrada na figura a seguir:

Essa uma representao na notao UML (Unified Modeling


Language), que nos informa que existe a definio de trs classes em
nosso sistema: existe a classe Animal (note que ela est em itlico; isso
significa na notao UML, que se trata de uma classe abstrata) e existem,
tambm, outras duas classes chamadas Cachorro e Gato, que so filhas
da classe Animal. Todo objeto das classes Cachorro e Gato herda todas
as caractersticas (atributos e mtodos) presentes na classe Animal, e mais
algumas caractersticas prprias.
Imagine que vamos criar um sistema de cadastro de animais. Vamos,
por questes didticas, supor que todos os animais de nosso sistema fiquem
armazenados em um array. Ento deve ser criado um array contendo objetos

Abstrao de Dados 111


dos tipos Gato e Cachorro. Mas armazenar diversos tipos diferentes de objetos
em um nico array no uma boa ideia, porque bastante complicado extrair
essas informaes de volta. Mas pare e pense por um instante: objetos do
tipo Cachorro e objetos do tipo Gato so tambm objetos do tipo Animal,
correto? Bom, ento podemos criar um array capaz de armazenar Animais!
Assim, nossa vida fica bem mais fcil, bastando atribuir ao array os objetos
(do tipo Cachorro e Gato - que estendem a classe Animal) que queremos
guardar. Em forma algortmica, seria mais ou menos:
listaDeAnimais = new Animal[100];
Criamos um array com 100 posies que armazena objetos do tipo
Animal.
listaDeAnimais[0] = new Cachorro(Dunga);
Criamos um novo objeto do tipo Cachorro com o nome Dunga e
armazenamos no array.
listaDeAnimais[1] = new Gato(Chico);
Criamos um novo objeto do tipo Gato com o nome Chico e
armazenamos no array.
Certo! Agora temos um array com vrios objetos do tipo Animal.
Agora vamos fazer um looping por todos esses objetos, enviando para cada
um deles a mensagem fale. O que iria acontecer?
Inicialmente, vamos supor que a classe abstrata Animal possua o
mtodo fale, e que ele seja implementado (de forma algortmica) da seguinte
forma:
Classe Animal {
mtodo fale() {
imprimaNaTela( Eu sou mudo! );
}
}
Desta forma, todo objeto de alguma classe que estenda a classe
Animal vai ter, automaticamente, o mtodo fale, e isso inclui todos os objetos
das classes Cachorro e Gato. Mas, todos eles, ao receberem a mensagem
fale, vo responder, imprimindo na tela a mensagem Eu sou mudo!. Mas
Gatos e Cachorros podem falar! O que podemos fazer sobrescrever o
mtodo fale para cada uma das classes, substituindo, ento, seu contedo
pelo comportamento que queremos que cada subclasse tenha.
Por exemplo, poderamos escrever na classe Gato do seguinte
mtodo:

112 unidade 4
Classe Gato {
Mtodo fale() {
imprimaNaTela( Miaaaaaauuuuuu! );
}
}
Para a classe Cachorro, poderamos fazer de forma semelhante:
Classe Cachorro {
Mtodo fale() {
imprimaNaTela( Au au au! );
} }
Agora, se fizermos um looping entre todos os objetos contidos em
nosso array criado anteriormente, enviando para cada objeto a mensagem
fale, cada um deles ir ter um comportamento diferente, dependendo se
um Cachorro ou um Gato. Nosso looping entre todos os animais cadastrados
no nosso sistema seria mais ou menos assim:
int cont;
para cont de 0 a 100 faa {
[cont].fale();
}
Isto polimorfismo! Uma mesma mensagem enviada para diferentes
objetos da mesma classe (Animal) e o resultado pode ser diferente, para
cada caso.

Exerccio

1. O que realmente um tipo abstrato de dados ?

2. Qual o papel do encapsulamento no que tange confiabilidade de


programas?

3. O que realmente significa herana, no contexto das linguagens de


programao?

4. O que realmente polimorfismo?

Abstrao de Dados 113


5. Qual a forma de vinculao dinmica deve ser empregada pelos mecanismos
de suporte orientao a objetos?

6. Que problemas os tipos abstratos de dados vieram resolver?

7. O que so classes abstratas?

8. Qual a origem da linguagem Eiffel?

9. Como Eiffel suporta orientao a objetos?

10. Eiffel uma linguagem puramente orientada a objetos? De que forma?

11. Que realmente significa passagem de mensagens?

12. Qual o objetivo da pseudo-varivel super em Smalltalk?

13. Por que as classes em Smalltalk podem responder a mensagens?

14. Que uma funo amiga em C++?

15. Onde os objetos em C++ so alocados?

16. Todas as subclasses em Ada 95 so de que tipos ?

SAIBA MAIS

Existem muitos bons textos sobre este tema. Alguns deles esto
listados na Referncias colocada ao final desta Unidade. A nosso juzo, o
livro de R. Sebesta apresenta um diferencial nesta rea. Em particular ele
dedica dois captulos importantes a este tema.
Muito se tem publicado em nvel de notas de aula e apostilas publicadas
pela Wikipdia e outras formas de publicao, a maioria delas, disponveis
pela Internet.
Vale ressaltar que muitos manuais tratam do uso e no da Programao
Orientada a Objetos, apesar da linguagem a que ele se refere incorporar este
mecanismo.

114 unidade 4
AHO, A. V. R; ULLMAN, J. D. Compilers: principles, techniques, and tools.
Reading, MA: Addison-Wesley, 1986.

DIJKSTRA, E.W. A discipline of programming. Englewood Cliffs, N. J:


Prentice-Hall, 1976.

DIJKSTRA, E.W. Selected writings on computing: a personal perspective.


New York : Spring-Verlag, 1982.

GHEZZI, C; JAZAYERI, M. Conceitos de linguagens de programao. Rio


de Janeiro: Campus, 1985.

GOLDBERG, A; ROBSON, D. Smalltalk-80: the language and Its


implementation. Reading, MA: Addison-Wesley, 1989.

GOSLING, J; JOY, B; STEELE, G. The Java language specification.


Reading, MA: Addison-Wesley, 1996.

HOARE, C. A. R; WIRTH, N. An axiomatic definition of the programming


language pascal. Acta Informatica. v. 2. p 335-355. 1973.

NETTO, Jos Lucas M. Rangel. Projeto de linguagens de programao.


Notas de aula. COPPE, UFRJ. 1993.

NUNES, Maria das Graas Volpe; FACELI, Katti. Tpicos em linguagens


de programao. Notas de aula. Instituto de Cincias Matemticas e de
Computao USP.

OSULLIVAN, Bryan; GOERZEN, John; STEWART, Don. Real world haskell.


OReilly. 2008.
PAULSON, Laurence C. ML for the working programmer. New York:
Cambridge University Press, 1991.

SCHMIDT, D. A. Denotational semantics. Massachusetts: Allyn and Bacon,


1986.

SCOTT, D. Data types as lattices. SIAM Journal of Computing. vol. 5,3.


1976.

SCOTT Michael L. Programming language pragmatics. Morgan Kaufmann


Publishers. 2000.

SEBESTA, Robert W. Programming languages concepts. 7th. edition, New


York: John Wiley & Sons. 2005.

SETHI, Ravi. Programming languages concepts and constructs. Addison


Wesley Publishing Company. 1989.

SILVA, Jos Carlos G; ASSIS, Fidelis S. G. de. Linguagens de programao


conceitos e avaliao. So Paulo: McGraw-Hill, 1988.

SKIENA, Steven S; REVILLA, Miguel A. Programming challenges: the


programming context training manual. Texts in Computer Science. Springer
Science+Business Media, Inc. 2003.

SOUZA, Francisco Vieira de; LINS, R. D. Analysing space behaviour of


functional programs. Recife: Conferncia Latino-americana de Programao
Funcional, 1999.

SOUZA, Francisco Vieira de. Aspectos de eficincia em algoritmos para


o gerenciamento automtico dinmico de Memria. Tese de Doutorado.
Recife: Centro de Informtica-UFPE, 2000.

STOY, J. E. Denotational semantics: the scott-strachey approach to


programming language theory. MIT Press, 1977.

VELOSO, Paulo A S. Estruturao e verificao de programas com tipos de


dados. So Paulo: Edgar Blcher, 1987.

WATT, David A. Programming language concepts and paradigms. 2nd ed.


New York: Prentice Hall International, 2004.
REFERNCIAS NA WEB

www.ufpi.br/uapi (A Pgina da Universidade Aberta do Piau - UAPI)


www.uab.gov.br (O Site da Universidade Aberta do Brasil- UAB)
www.seed.mec.gov.br (A Homepage da Secretaria de Educao a Distncia
do MEC - SEED )
www.abed.org.br (O site da Associao Brasileira de Educao a Distncia
- ABED)
http://pt.wikipedia.org/ O site da Wikipedia.
www.inf.ufsc.br/ine5365/introlog.html
www.gregosetroianos.mat.br/logica.asp.