estruturas de dados (lei, lm, lee) programação iii (ltsi)

Transcrição

estruturas de dados (lei, lm, lee) programação iii (ltsi)
ESTRUTURAS DE DADOS (LEI, LM, LEE)
PROGRAMAÇÃO III (LTSI)
Universidade da Beira Interior, Departamento de Informática
Hugo Pedro Proença, 2014/2015
Apontadores
! 
O que é um apontador?
Variável que contém um endereço de memória.
!  Exemplos: int x=5; float z=3.1415; char c;
! 
5
x, 4 bytes
! 
3.1415
z, 8 bytes
a
c, 1 byte
Apontador:
! 
Espaço ocupado depende do limite de endereçamento da
máquina, mas tipicamente tem o mesmo tamanho de um
inteiro. Exlº: int *p;
A...
p, 4 bytes
Tipos de Dados Básicos (ANSI)
! 
char " 8 bits,
1 0 0 1 0 0 1 0 0
! 
int " 16/32 bits
1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0
! 
float " 32 bits
! 
double " 64 bits
1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0
1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0
1
1
1
1
0
0
0
0
0
0
0
0
1
1
1
1
0
0
0
0
0
0
0
0
1
1
1
1
0
0
0
0
0
0
0
0
1
1
1
1
0
0
0
0
0
0
0
0
1
1
1
1
0
0
0
0
0
0
0
0
1
1
1
1
0
0
0
0
0
0
0
0
Apontadores
! 
Independentemente do espaço ocupado em memória,
os tipos de dados básicos funcionam de forma intuitiva:
! 
! 
Uma variável (x) do tipo inteiro é um “espaço com
capacidade suficiente para colocar um valor inteiro lá
256
dentro”. Exemplo:
x
Similar para os restantes tipos de dados.
! 
char y
w
! 
float z
231876.1532
! 
double h
231876.1532
Apontadores
! 
Um apontador contém informação sobre uma
determinada localização e quantidade de
memória:
! 
Exlos: int *a; double *b;
a4:b9:F:c:6
a4:b9:F:c:6
Igual tamanho!
b5:a9:4:8
b5:a9:4:8
Apontadores
! 
Qual a necessidade de usar apontadores?
! 
Resolvem 2 tipos de problemas:
! 
Permitem que diferentes secções de um programa partilhem
informação.
! 
! 
A alternativa, com desvantagens óbvias, será a cópia de
informação.
Possibilitam a construção de estruturas de dados complexas
e dinãmicas, tais como as listas ligadas e as árvores
binárias, ambas objecto de estudo nesta disciplina.
Apontadores
! 
Um apontador funciona de forma similar. É uma
variável que contém espaço suficiente para
albergar um endereço de memória.
Tipicamente 2-4 bytes.
!  int *y;
// ”y” aponta para um inteiro
! 
Representação Física
y
Representação Lógica
0x65
y
Não alocado !
0x65
25
25
Não alocado !
Apontadores: Inicialização
! 
Experimente-se executar
o seguinte programa:
! 
! 
A variável “x” é alocada para guardar espaço para um inteiro.
Qual?
! 
! 
LIXO!
De igual forma, ao declararmos um apontador ele refere-se a
um determinado espaço de memória.
! 
Qual?
! 
! 
! 
#include <stdio.h>
void main(){
int x;
printf(“%d\n”,x);
}
Não controlamos isso!
Possivelmente algum espaço afecto a outro processo ou utilizador
Resultado: “Access Violation”: tentativa de acesso a um
espaço de memória indevido.
Apontadores: Inicialização
! 
Constante NULL.
! 
! 
! 
! 
! 
Definida na biblioteca “stdlib.h”
Serve para explicitar o valor nulo.
Tenta modelar o conceito de “não estar a apontar para lado
nenhum”
Representa-se normalmente pelo síbolo de “terra” (ground),
proveniente dos sistemas digitais.
Nodo *p=NULL;
p
Memória Alocada Dinamicamente
! 
! 
! 
! 
! 
A memória alocada dinamicamente faz parte de
uma área de memória chamada heap.
Basicamente, o programa aloca e liberta porções
de memória do heap durante a execução.
Alocação: malloc, realloc, calloc.
0x01
0x02
Libertação: free.
Nodo *p=malloc(...);
...
0x0n
Símbolos * e &
! 
! 
! 
Na linguagem C, os símbolos * e & desempenham
um papel fulcral nas operações de baixo nível de
manuseamento de espaços de memória.
* " “o espaço para onde aponta a variável”
&" “o endereço da variável”
Exemplo:
! 
# 
int *p;
int x=4;
...
*p=x;
# 
p=&x;
# 
# 
# 
//”p” é um apontador para um nodo;
//”x” é um inteiro
//Cópia de inteiros. Só funcionaria se “p”
tivesse espaço válido associado!
//”p” aponta para o endereço da variável x
Símbolos * e &
! 
! 
! 
! 
! 
! 
! 
! 
! 
! 
! 
! 
! 
int x=4, y=6;
int *z;
int *z=x;
int *z=&x;
z=y;
z=&y;
&x=6;
&x=FF:AA:99:CC;
x=x+1;
z=z+1;
int * v=malloc(sizeof(int));
*z=4;
*v=5;
Parâmetros
! 
Ao executarmos uma função, é criada uma cópia de
todos os parâmetros de entrada.
!  Na
“passagem por valor”, a expressão-argumento é
avaliada e o resultado copiado para uma nova região da
memória.
#  int
porValor(int x);
#  A variàvel argumento tem alcance local (dentro da função).
!  A
“passagem por referência”, o processo é exactamente o
mesmo, tendo como única particularidade o facto da
variável-argumento ser do tipo apontador.
#  Int
porReferencia(int *x);
#  A cópia feita é relativa a apontadores, podendo ser alterado o
espaço original da variável utilizada na chamada à função.
Estruturas de Dados Dinãmicas
! 
! 
É usual definir uma estrutura de dados dinãmica em
C através da criação de um novo tipo de dados
(typedef) e da especificação da estrutura.
Sintaxe:
Nome temporário
typedef struct TIPO{
Tipo atributo1;
Atributos de Dados
...
Tipo atributon;
Atributo de ligação
struct TIPO *nseg;
Novo tipo
}Tipo;
Estruturas de Dados Dinãmicas
! 
Exemplo: Definição de um tipo de dados dinãmico
para guardar informação sobre os alunos da UBI.
Typedef struct ALUNO{
int numAluno;
long int BI;
char nome[80];
char morada[80];
struct ALUNO* nseg;
}Aluno;
Estruturas de Dados Dinãmicas
! 
! 
A partir da definição anterior, é possível passar a
criar variáveis do tipo Aluno:
numAluno
Estáticamente:
! 
BI
Nome
Aluno x;
x
! 
Morada
nseg
Dinamicamente:
! 
numAluno
Aluno *y=(Aluno*)malloc(sizeof(Aluno));
y
BI
Nome
Morada
nseg
Apontadores
Exemplos
Atribuição
Apontadores
Listas Simplesmente Ligadas
! 
! 
! 
Uma Lista ligada (simples) é um conjunto de
elementos de um determinado tipo de estrutura de
dados, em que cada elemento contém uma ligação
ao próximo elemento da lista, através da variável
apontador “nseg”.
O acesso ao primeiro elemento da lista é
efectuado através de uma variável apontador
para o respectivo tipo/estrutura de dados.
O último elemento da lista contém o atributo
apontador “nseg” a apontar para a constante
“NULL”.
Listas Ligadas
Ilustração:
! 
! 
Perspectiva Lógica de uma lista simplesmente ligada:
L
! 
E1
E2
E3
E4
Perspectiva Física de uma lista simplesmente ligada:
0x73
L 0x73
E1
0x76
E3
0x75
E4
0x00
E2
0x74
...
Alocação Dinãmica
makeNode()
Operações c/ Listas
insertFirst()
removeFirst()
Operações c/ Listas
insertLast()
removeLast()

Documentos relacionados

jogo getch cabeça

jogo getch cabeça linguagem Assembly, o que resultava em um código muito rápido e eficiente. Entretanto, escrever um sistema operacional em Assembly é um processo tedioso (lento), e produz um código que funcionará s...

Leia mais