Tipos. O Conceito de Tipo

Documentos relacionados
Paradigmas de Programação

Linguagens de Programação Conceitos e Técnicas. Amarrações

Estudos de Linguagens de Programação - Revisão

Nomes, vinculações e escopos

Nomes, vinculações e escopos

Nomes, Amarração, Verificação de Tipos, e Escopo

Paradigmas de Linguagens de Programação. Tipos de Dados

Paradigmas de Linguagens de Programação. Nomes, Vinculações, Verificação de Tipos e Escopos

Paradigmas de Linguagens

Paradigmas de Linguagem de Programação. Paradigma Imperativo

02. [Sebesta, 2000] Quais são as vantagens e as desvantagens dos tipos de dados decimais?

Capítulo 5. Nomes, Vinculações e Escopos

Trabalho Linguagem e Programação de Compiladores

Ambiente de tempo de Execução Cap. 7

CAP. VI ANÁLISE SEMÂNTICA

Conceitos de Linguagens de Programação

Nomes, Vinculações, Verificação de Tipos e Escopos. George Darmiton da Cunha Cavalcanti

Paradigmas de Linguagens de Programação. Expressões e Instruções de Atribuição

ao paradigma imperativo

Listas: nós de cabeçalho, listas não homogêneas, listas generalizadas

Implementando subprogramas

Classes e Objetos. Sintaxe de classe em Java

Tipo. Tipo de uma variável: especificação de

Capítulo 7. Expressões e Sentenças de Atribuição

Linguagens de Programação. Nomes, Escopos e Vinculações (Bindings) Carlos Bazilio

Linguagens de Programação Nomes, Amarrações e Escopo

Paradigmas. Fortran, Algol, Algol-68, Pascal, C, Cobol, PL/I

Listas: nós de cabeçalho, listas não homogêneas, listas generalizadas. SCC-502 Algoritmos e Estruturas de Dados I

Implementação de subprogramas

3. Linguagem de Programação C

Paradigmas de Linguagens de Programação. Subprogramas

Análise Semântica: Verificação de Tipos

Linguagens de Programação Aula 11

Programação Orientada a Objetos. Métodos e Atributos. Métodos. Métodos. Alexandre César Muniz de Oliveira. Parte III

Paradigmas de Programação. Java First-Tier: Aplicações. Orientação a Objetos em Java (I) Nomenclatura. Paradigma OO. Nomenclatura

Compiladores. Gerência de Memória

Métodos Computacionais

C com introdução a OO

Capítulo 6. Tipos de Dados

Tipos, Literais, Operadores

Tipos, Literais, Operadores

Paradigmas de Linguagens de Programação. Tipos de Dados Abstratos

Estruturas de Dados Aulas 3 e 4: Uso da. 14/03/2011 e 16/03/2011

Linguagem C Princípios Básicos (parte 1)

Programação de Computadores II

Linguagem de Programação e Compiladores

Estruturas de Dados. Introdução Definição de Ponteiros Declaração de Ponteiros em C Manipulação de Ponteiros em C

Programação de Computadores I Introdução ao C PROFESSORA CINTIA CAETANO

Linguagens de Programação 2 Amarrações

Sumário. Introdução à Ciência da Computação. Ponteiros em C. Introdução. Definição. Por quê ponteiros são importantes?

PROGRAMAS BÁSICOS EM C++ Disciplina: Introdução à Ciência da Computação Prof. Modesto Antonio Chaves Universidade estadual do Sudoeste da Bahia

Tipos Básicos. Operadores de Incremento e Decremento. Operador Sizeof. Estruturas de Dados Aula 2: Estruturas Estáticas

Array em Java. Figura 1 - Exemplo de um array de inteiros

Estruturas da linguagem C. 1. Identificadores, tipos primitivos, variáveis e constantes, operadores e expressões.

Transcrição:

Tipos mleal@inf.puc-rio.br 1 O Conceito de Tipo LPs geralmente permitem a organização de dados em diferentes categorias através do conceito de tipo. Um tipo é definido a partir de um conjunto de valores e de operações ao qual está associado. O sistema de tipos de uma LP usualmente inclui um conjunto básico de tipos; mecanismos para a associação entre tipos e construções básicas da LP; regras para a definição de novos tipos; regras de compatibilidade e inferência. mleal@inf.puc-rio.br 2

O Conceito de Tipo O tipo fornece um contexto implícito para a execução de operações, e facilita a definição de regras semânticas: Pode-se checar em tempo de compilação a utilização correta de variáveis. A resolução de operações sobrecarregadas também pode ser feita em tempo de compilação. Torna-se mais fácil entender a estrutura do programa. A forma como a representação de um tipo de dado é implementada torna-se transparente, podendo inclusive ser modificada sem afetar o funcionamento do programa. mleal@inf.puc-rio.br 3 Definição de Tipos A atribuição de um tipo a uma variável usualmente é feito através de uma declaração. Entretanto em algumas LPs uma variável pode ser utilizada sem ser declarada (Fortran, Basic, Lua, Lisp, etc). Em Fortran, se uma variável não é declarada, o compilador assume que a variável é local. Se o nome da variável começar com I..N o compilador assume que o seu tipo é inteiro, ou real caso contrário. Em Lua o tipo da variável é determinado implicitamente pelo tipo do dado que lhe é atribuído: x = 5 -- x tem o tipo number x ={1, 2, 3} -- x tem o tipo table mleal@inf.puc-rio.br 4

Definição de Tipos A verificação de tipos pode ser feita durante a compilação (verificação estática) ou em tempo de execução (verificação dinâmica). Exemplos de LPs com verificação dinâmica são Lua, Scheme, Smalltalk, Perl, etc. Em LPs orientadas a objetos sempre é necessário algum tipo de verificação dinâmica. mleal@inf.puc-rio.br 5 Definição de Tipos Toda LP possui um conjunto primitivo de tipos, que geralmente incluem: Caracter (char) Strings Inteiros Reais Boleanos Além disso muitas LPs permitem que o usuário defina novos tipos de dados através de declarações específicas (typedef( em C, type em Pascal e Módula 2, etc). mleal@inf.puc-rio.br 6

Classificação de Tipos Podemos classificar os tipos compostos disponíveis em LPs nas seguintes categorias: Produto cartesiano; Conjunto potência; Domínios finitos; União discriminada; Sequências; Definição recursiva; mleal@inf.puc-rio.br 7 Produto Cartesiano Um produto cartesiano de dois ou mais conjuntos é uma combinação de valores agregados (tuplas) retirados de cada um dos conjuntos de dados. Várias linguagens permitem tais construções, como as estruturas (structures( structures) ) de C ou Algol-68, ou os registros (records( records) ) em Ada ou Pascal. mleal@inf.puc-rio.br 8

Record As declarações em Pascal e C abaixo type typedef struct{ t = record int a; a:integer; char b; b:char; } t end; introduzem um tipo t, e fazem com que cada variável x declarada como sendo do tipo t tenha duas componentes, x.a e x.b, sendo o valor da primeira componente do tipo inteiro, e o valor da segunda componente do tipo char. A variável x é composta por x.a e x.b, que podem, em conjunto, assumir valores como (100,'a'), ou (25,'?'). mleal@inf.puc-rio.br 9 Record A maioria das LPs permite a comparação e atribuição direta entre records do mesmo tipo. Algumas LPs oferecem um comando para a manipulação de records. Em Modula 3 por exemplo: with e = carro.sistema.peça do e.nome:= pastilha e.preco := 23; end mleal@inf.puc-rio.br 10

Conjunto Potência Permitem definir valores que pertencem a um subconjunto de um tipo qualquer. Um exemplo é o set of de Pascal: type carros = set of (fusca( fusca,gol,escort,,escort,opala); type digitos = set of 0..9; mleal@inf.puc-rio.br 11 Conjunto Potência Operações típicas de conjunto potência são união, interseção e pertence. Em Pascal temos: var A,B,C: digitos; begin A := [1, 2, 3, 4]; B := [3, 4, 5]; C:= A+B; [1,2,3,4,5] C:= A*B; [3,4,] C:= A-B; A [1,2] if 5 in C then... mleal@inf.puc-rio.br 12

Domínios Finito Permitem definir uma associação entre um conjunto finito (domínio) e valores de um conjunto qualquer (contra- domínio). Como principal exemplo desta categoria temos o array. mleal@inf.puc-rio.br 13 Arrays Array é o tipo composto mais comum e mais importante em LPs. Poucas LPs permitem a comparação (Fortran, Ada) e atribuição direta entre arrays (Java). Diversas LPs permitem a definição dos limites de um array dinamicamente (Java, Lua). mleal@inf.puc-rio.br 14

Array - Exemplos C\C++ C++ char digit[10]; Pascal e Modula 2 var y: array[1..5] of integer; Lua x ={1, 2, 3, 4} Pearl @a = (1, 2, 3, 4) mleal@inf.puc-rio.br 15 Arrays - Representação Um array geralmente é representado em memória através de endereços consecutivos. Existem duas opções para representar arrays bi- dimensionais na memória: usando posições contíguas para as colunas ou para as linhas. mleal@inf.puc-rio.br 16

Arrays Acessando Elementos mleal@inf.puc-rio.br 17 Enumeração Todos os valores possíveis de um tipo são explicitamente enumerados. Exemplos: Pascal type cor =(azul, vermelho, verde, amarelo) C enum cor {azul, vermelho, verde, amarelo} mleal@inf.puc-rio.br 18

União Discriminada Permite a definição concomitante de mais de um tipo para uma variável. É interessante em situações em que uma variável precisa assumir valores de mais de um tipo, ou para economia de memória. No exemplo em C union { short int offset; long unsigned int absolute; } os campos são mutuamente exclusivos. Somente um pode estar ativo em qualquer tempo. mleal@inf.puc-rio.br 19 União Discriminada Exemplo - variant records Pascal: Type AddrType = (US, Canada, Generic) AddressRecord = record Address: array[1..2] of string[20]; City: string[20]; Country: string[20]; case Kind: AddrType of US: (State: string[2]; ZIP:string[10]); Canada: (Province: string[10]; ZIP:string[6]); Generic: (Comment: String[16]); end; {case} end; {record} mleal@inf.puc-rio.br 20

Sequências Permitem que os dados sejam representados através de listas. Exemplos são cadeias de caracteres (strings( strings), listas (Lisp, Prolog, Ada) e arquivos sequenciais (Pascal). Suportam operações como primeiro, próximo e anterior. Em Scheme temos: (car (2 3 4)) 2 (cdr (2 3 4)) (3 4) mleal@inf.puc-rio.br 21 Definições Recursivas Tipos em que os dados podem crescer de forma arbitrária, através de referências a outras estruturas do mesmo tipo. Exemplos seriam estruturas de dados clássicas como listas e árvores. Estes tipos geralmente são implementados através de ponteiros: typedef struct{ int val; int_list* next; } int_list; mleal@inf.puc-rio.br 22

Modelo de Valor ou de Referência Em LPs como Samlltalk, Clu, ML e Lisp, variáveis contém apenas referências para objetos. Uma operação de atribuição faz com que duas variáveis refiram-se ao mesmo objeto. Estas LPs adotam um modelo de variável por referência. Em LPs como C, Pascal e Ada a operação de atribuição copia valores. Referência a objetos só são possíveis através da criação explícita de referências, usando o mecanismo de ponteiros. Estas LPs adotam um modelo de variável por valor. mleal@inf.puc-rio.br 23 Ponteiros Ponteiros permitem armazenar o l-value l de uma variável. Para acessar os valores referenciados pelos ponteiros (r-value) são usados operadores especiais denominados operadores de indireção (dereferencing). Em Pascal temos o ^ (e o -> para records): my_pt^.val:= 5; my_pt->val:= 5; Em C\C++ C C++ temos o *: (*my_pt).val = 5; formas equivalentes mleal@inf.puc-rio.br 24

Exemplo - C programa int x=1, y=2; int *ip; ip = &x; y = *ip; x = ip; *ip = 3; memória x 1 y 2 ip 100 100 4000 5000 x 1 y 1 ip 100 100 4000 5000 x 100 y 1 ip 100 100 4000 5000 x 3 y 2 ip 100 100 4000 5000 mleal@inf.puc-rio.br 25 Ponteiros Em LPs com mecanismos de ponteiros a alocação e desalocação de memória deve ser feita explicitamente pelo programador. Em C++ isto é feito através das funções new e delete e em Pascal através de new e dispose: type pont=^integer; var pt:pont;... new(pt); pt^:= 5... dispose(pt); mleal@inf.puc-rio.br 26

Ponteiros A alocação dinâmica de memória, com exceção de variáveis locais, sempre utiliza a heap. Dois problemas são derivados da alocação e da desalocação explicitas de espaço: a criação de lixo e de referências pendentes ou ocas. Por lixo, entende-se uma área que não está mais em uso, mas que não foi devolvida à lista de espaço vazio, porque não foi feita a operação de liberação correspondente. Referências pendentes são referências a uma área que já foi desalocada, e que portanto, ou está marcada como espaço livre e não deve ser utilizada, ou já foi realocada e tem uma utilização diferente. mleal@inf.puc-rio.br 27 Ponteiros type pont=^integer; var pt:pont; var x: integer;... new(pt); pt^:= 5... dispose(pt); x:= pt^; mleal@inf.puc-rio.br 28

Ponteiros e Arrays em C int main () { int numbers[5]; int * p; p = numbers; *p = 10; p++; *p = 20; p = &numbers[2]; *p = 30; p = numbers + 3; *p = 40; p = numbers; *(p+4) = 50; for (int n=0; n<5; n++) cout << numbers[n] << ", "; return 0; } numbers 10 20 30 40 50 mleal@inf.puc-rio.br 29 Ponteiros X Referências Uma referência equivale a uma constante ponteiro (após ser criado, o seu valor não pode mais mudar). Em referências a indireção é automática, não há necessidade de utilização de operadores especiais. Exemplo int b; int& & a = b; referência a = 10; int b; int *a = &b; ponteiro *a = 10; mleal@inf.puc-rio.br 30

Gerenciamento de Memória Em algumas LPs (Java, Lua, C#) o programador pode criar novos objetos dinamicamente, sem a necessidade de controlar explicitamente o gerenciamento da memória. Em LPs com gerenciamento automático de memória o sistema deve ser capaz de identificar os objetos que não podem ser mais acessados pelo programa (lixo), desalocando o espaço de memória correspondente. Este processo de desalocação automática de memória é conhecido como coleta de lixo (garbage collection). As duas principais técnicas utilizadas para implementar a coleta de lixo são a contagem de referências (reference count) e marcar e varrer (mark-and and-sweep). mleal@inf.puc-rio.br 31 Reference Count Cada objeto guarda o número de referências que apontam para ele. Sempre que uma nova referência para um objeto é criada ou destruída, o número de referências correspondente é modificado. Quando o número de referências atinge zero, a memória utilizada pelo objeto pode ser desalocada pelo sistema. Um problema importante desta técnica são as referências circulares. mleal@inf.puc-rio.br 32

Reference Count mleal@inf.puc-rio.br 33 Mark-and and-sweep A técnica de mark-and and-sweep segue um algoritmo simples: 1. Percorrer toda a memória heap e marcar todos os objetos como livres. 2. Percorrer de forma recursiva todas as referências contidas em variáveis fora da heap, e marcar todos os objetos encontrados como não-livres. 3. Percorrer novamente a memória heap e desalocar todos os objetos que ainda estiverem marcados livres. mleal@inf.puc-rio.br 34

Mark-and and-sweep mleal@inf.puc-rio.br 35 Equivalência Entre Tipos Diz-se que uma LP é fortemente tipada,, se é possível, apenas por análise estática do programa (análise realizada em tempo de compilação), determinar que a estrutura de tipos da linguagem não é violada. A princípio se uma operação é definida com um parâmetro do tipo T, qualquer invocação legal desta função deveria incluir sempre um parâmetro do tipo T. Na maioria das LPs entretanto as regras de tipos apresentam alguma flexibilidade, permitindo a conversão entre valores de tipos distintos. mleal@inf.puc-rio.br 36

Equivalência Entre Tipos Exemplo: type aluno = record nome, endereco: string idade: integer end type aluno = record nome, endereco: string idade: integer end... x: estudante; y: aluno; begin... x = y; Erro?? mleal@inf.puc-rio.br 37 Equivalência Entre Tipos Em algumas LPs a compatibilidade entre tipos é determinada pela estrutura do tipo (C, com exceção de struts), s), enquanto em outras a compatibilidade é determinada pelo nome (Pascal, Ada). type complex is struct { float a,b; } type point is struct { float a,b; } mleal@inf.puc-rio.br 38

Conversão Implícita (Coerção) Se dados do tipo T1, do ponto de vista abstrato, podem conter valores do tipo T2, embora através de representações distintas, a LP pode fazer a conversão automática entre estes tipos. Exemplo: x: real; i: integer; x = i; -- coerção de inteiro para real print( resultado: +x) -- coerção de real para string mleal@inf.puc-rio.br 39 Conversão Explícita (Typecast) Em algumas situações pode ser necessário que um valor do tipo T1 seja entendido como se fosse do tipo T2. Algumas LPs (Java, C, Eiffel) permitem esta conversão através do mecanismo de typecast. float x; int z; z = z+(int)x; mleal@inf.puc-rio.br 40

Conversão Forçada Quando há várias maneiras de converter um valor de um tipo T1 para o tipo T2, é necessário indicar a forma de conversão desejada, e, em geral, isso é feito através de uma função de conversão. Um exemplo seria a conversão de reais em inteiros, que pode ser feita por arredondamento, truncamento, etc, ou a conversão de strings para inteiros. Normalmente a LP disponibiliza funções pré- definidas para as situações mais comuns. mleal@inf.puc-rio.br 41 Tipos Abstratos de Dados A facilidade de definir novos tipos permite ao programador estruturar os dados conforme as características da sua aplicação. Entretanto estes mecanismos não permitem especificar totalmente quais são as operações válidas sobre estes tipos, e nem ocultar a sua estrutura. Em LPs com tipos abstratos de dados a representação e as operações associadas ao tipo são definidas através de uma única estrutura (encapsulamento), e a representação dos dados muitas vezes é transparente para os usuários. mleal@inf.puc-rio.br 42

Tipos Abstratos de Dados Exemplos clássicos de tipos abstratos são classes em Java, C++, C#, Eiffel e Smalltalk. O mecanismo de templates em C++ permite a definição de tipos abstratos que utilizam tipos genéricos como parâmetros. mleal@inf.puc-rio.br 43 Exemplo - Templates template <class T> T GetMax (T a, T b) { T result; result = (a>b)? a : b; return (result); } int main () { int i=5, j=6, k; long l=10, m=5, n; k=getmax<int>(i,j); n=getmax<long>(l,m);... } mleal@inf.puc-rio.br 44