AEDI-ponteiros

Propaganda
Algoritmos e Estruturas de Dados I –
Ponteiros
Profa. Mercedes Gonzales
Márquez
Variáveis (relembrando)


Variável é um nome amigável (simbólico) que
damos para uma localização de memória que
receberá um dado de algum tipo.
No momento da declaração de uma variável, um
espaço de memória é alocado para ela.
Nome (rótulo)
Variável:
Valor (conteúdo)
inteiro: p,q,s
real: r
p ←50
r ←40.5
Endereço na
memória Conteúdo
Nome
p
r
s
1001
50
1005
40.5
1009

q
2047

Ponteiros - Conceito

Um ponteiro é uma variável que armazena um
endereço de memória.
inteiro: p,r,*q
real: r
p ←50
r ←40.5
q ←&p

O símbolo *
indica que q é
um ponteiro.
Endereço na
memória Conteúdo
Nome
p
r
s
q
1001
50
1005
40.5
1009


2047
1001
O nome ponteiro refere ao fato deste tipo especial
de variável “apontar” para um endereço.
O símbolo & representa o endereço.
Ponteiros - Declaração



Ponteiro tem um tipo associado que determina o
tipo da dado contido no endereço apontado. Pode
ser um tipo pré-definido da linguagem ou um tipo
definido pelo programador. Exemplo: inteiro,
literal, real, TipoProduto,etc.
A declaração de um tipo ponteiro se faz com a
seguinte sintaxe:
tipo da dado apontado: *ponteiro
Exemplos:
Real: *p1
Inteiro: *p2
Literal: *p3
Operadores indireção e endereço


O símbolo * é chamado operador de indireção. Se
aplicado a um ponteiro, ele indica o valor
armazenado no endereço contido no ponteiro.
O símbolo & é conhecido como operador endereço.
Anexado no início de um nome de variável, ele
representa o endereço na memória onde o valor da
Endereço na
variável está armazenado.
inteiro: cont ← 10, x, *p
p ← &cont
x ← *p
escreva (cont,x);
memória
cont 1001
p 1005
x
Conteúdo
10
1001


2047
10
Ponteiros – Operador &

Considere as declarações e inicializações
inteiro: x, y, *p1, *p2
x ← -42
y ← 163

Essas declarações alocam memória para duas
variáveis do tipo inteiro e duas do tipo ponteiro a
inteiro. Os seus valores serão armazenados nos
endereços de memória indicados no seguinte
diagrama.
Ponteiros – Operador &

Se fizermos:
p1 ← &x
p2 ← &y
Teremos a memória no seguinte estado.
antes
p1
depois
e p2 apontam as variáveis que estão
referenciando.
Ponteiros – Operador *

Se fizermos:
*p1 ← 17
muda o valor na variável x devido que é onde p1
aponta. Assim, teremos a seguinte configuração.
Ponteiros – Atribuindo outro ponteiro

Também é possível atribuir novos valores aos
ponteiros. Por exemplo
p1 ← p2
leva ao computador a tomar o valor contido na
variável p2 (1004) e copiá-lo na variável p1. Ao
copiar este valor em p1, ambos p1 e p2 apontarão
à variável y, como mostramos no diagrama:
1004
Ponteiros – Atribuindo valores

Resumindo, nós podemos atribuir valores para um
ponteiro de duas formas:
–
Usando o operador endereço
Usando diretamente atribuição entre
ponteiros.
–

int *p;
int x;
p = &x;
*p = 4;
int *p;
int *p1;
int x;
p1 = &x;
p = p1;
*p = 4;
Em ambos os casos estamos referenciando alguma
variável.
Ponteiros – Apontando para lixo

Observe o seguinte exemplo:

O ponteiro p foi declarado, mas não lhe foi atribuído
nenhum valor, ou seja p aponta a um endereço
desconhecido (comumente chamado lixo).
Quando o valor 4 é armazenado na localização que
p aponta, nós não podemos saber onde o valor 4
será armazenado.


int *p;
*p = 4;
Tentar acessar este valor pode gerar um erro fatal
no nosso programa ou até sistema operacional.
Ponteiros – Constante NULO

Os valores de um ponteiro:
– Um ponteiro a alguma outra variável.
– Pode ser atribuído uma constante NULO
Um ponteiro nulo não aponta a posição alguma.
 É uma boa prática testar se o ponteiro é nulo
antes de indagar sobre o valor apontado.
inteiro: *ip ← NULO;
se (ip <>NULO) escreva (*ip)
 Se (ip )
escreva(*ip)

Ponteiros e arrays

Nome de array é um apontador
– int a[6]; int a2[6];

Passagem de array como parâmetro é por referência
– funcao(int a[]) ou funcao(int *a)// declaração
– funcao(a); // chamada

Operador atribuição não funciona
– a ← a2; // errado! Não é possível copiar diretamente

Identificador do array é o endereço 1º elemento
– a é &a[0]

Conteúdo do array
– Conteúdo da 1ª posição: *a ou a[0]
– Conteúdo da 2ª posição: *(a+1) ou a[1]
Ponteiros e arrays
• Assuma que
Inteiro: *pa
pa ← &a[0] ou pa←a
• Então p aponta para a[0], *(pa+1) refere ao conteúdo de
a[1], pa+i é o endereço de a[i] e *(pa+i) é o conteúdo de a[i].
• O valor em a[i] pode também ser escrito como *(a+i). O
endereço &a[i] e a+i são também idénticos.
Ponteiros e arrays
• Os elementos de um array podem ser acessados
através de índices como de ponteiros. Exemplo:
vazio print1(inteiro: vet[], inteiro: n)
inteiro: i
Para i de 1 até n repita
escreva (vet[i])
vazio print2(inteiro: vet[],int n)
inteiro: * ptr
Para ptr de vet até vet+n repita
escreva (*ptr)
vazio print3(inteiro: *vet,inteiro: n)
Inteiro: * ptr
Para ptr de vet até vet+n repita
escreva (*ptr);
}
vazio print4(inteiro: *vet,inteiro: n)
Inteiro: i
Para i de 1 até n repita
escreva (*vet)
vet<-v+1
Alocação estática


Até agora, todas as estruturas tinham tamanho prédefinido, exemplo matrizes e vetores.
Esta alocação estática pode implicar em:
–
–
desperdício dos recursos pois podemos definirmos um
tamanho muito maior que aquele que normalmente será
usado em tempo de execução.
Pode-se, em contraste, subestimar o tamanho necessário
para armazenar os dados.
Alocação dinâmica



Na alocação dinâmica os espaços são
alocados durante a execução do programa,
conforme este necessitar de memória.
Não há reserva antecipada de espaço.
Alocar memória dinamicamente significa
gerenciar memória (isto é, reservar, utilizar e
liberar espaço) durante o tempo de execução.
Ponteiros – Alocação dinâmica



Alocando espaço na Heap
O uso mais importante de ponteiros é para apoio
à alocação dinâmica, isto é, ao invés de apontar
variáveis já alocadas do espaço de dados, utilizar
o espaço de heap para novas variáveis, que
podem ser liberadas após o uso, mesmo antes do
término do programa.
Para isso, é necessária uma operação de
alocação de memória, e uma para liberação de
memória.
Ponteiros – Alocação dinâmica




A operação que aloca memória é implementada
por uma função, na forma: aloque(p)
Esta operação reserva, na Heap, espaço
suficiente para armazenar um dado do tipo
apontado por p. Em p é armazenado o endereço
de memória deste dado.
A operação que libera memória é implementada
por uma função, na forma: libere(p)
Esta operação ‘retorna’ para a Heap aquele
espaço ocupado pelo dado apontado por p, e
anula p.
Ponteiros ou Apontadores

Após a alocação o ponteiro passará apontar para
uma área definida da memória capaz de
armazenar uma variável de determinado
tipo.Exemplo:
real:*p1
inteiro:*p2
literal: *p3
aloque(p1)
aloque (p2)
aloque (p3)
Ponteiros ou Apontadores

Exemplo 1:
inteiro:*p2
aloque(p2)
*p2 ←‘ a’ (errado)
*p2 ←5 (certo)
Ponteiros ou Apontadores

Exemplo 2:
inteiro:*p2
*p2 ←5 (erro, o ponteiro não foi alocado)

No seguinte exemplo atribuimos o valor nulo para
um ponteiro, a fim de indicar que ainda não foi
alocado espaço para ele.
real:*ap1
ap1 ←NULO
Ponteiros ou Apontadores
Exemplo 3:
inteiro: *p2
aloque (p2)
*p2 ←5
libere (p2)
Ponteiros ou Apontadores

Exemplo 4:
Inteiro:x, *p,*q
x← 1
p ← &x
*q ← 3
q← p
*q ← *p + 1
escreva(*p)

Teste de
mesa inicial
p
x
lixo
lixo
q
lixo
Ponteiros ou Apontadores

Exemplo 4:
Inteiro:x, *p,*q
x← 1
p ← &x
*q ← 3
q← p
*q ← *p + 1
escreva(*p)
p
lixo
q
lixo
x
1
Ponteiros ou Apontadores

Exemplo 4:
Inteiro:x, *p,*q
x← 1
p ← &x
*q ← 3
q← p
*q ← *p + 1
escreva(*p)
p
x
1
q
lixo
Ponteiros ou Apontadores

Exemplo 4:
Inteiro:x, *p,*q
x← 1
p ← &x
*q ← 3
q← p
*q ← *p + 1
escreva(*p)
p
x
1
q
lixo
ERRO, q aponta para lixo
Ponteiros ou Apontadores

Exemplo 4:
Inteiro:x, *p,*q
x← 1
p ← &x
*q ← 3
q← p
*q ← *p + 1
escreva(*p)
p
x
1
q
Ponteiros ou Apontadores

Exemplo 4:
Inteiro:x, *p,*q
x← 1
p ← &x
*q ← 3
q← p
*q ← *p + 1
escreva(*p)
p
x
2
q
Ponteiros ou Apontadores

Exemplo 4:
Inteiro:x, *p,*q
x← 1
p ← &x
*q ← 3
q← p
*q ← *p + 1
escreva(*p)
p
x
2
q
Resultado = 2
Ponteiros ou Apontadores
Exemplo 4:
Alocação dinâmica
Inteiro:*p,*q
aloque(p)
*p ← 1
q← p
*q ← *p + 1
escreva(*p)
libere(p)


Teste de
mesa inicial
p
lixo
q
lixo
Ponteiros ou Apontadores
Exemplo 4:
Alocação dinâmica
Inteiro:*p,*q
aloque(p)
*p ← 1
q← p
*q ← *p + 1
escreva(*p)
libere(p)

lixo
q
Ponteiros ou Apontadores
Exemplo 4:
Alocação dinâmica
Inteiro:*p,*q
aloque(p)
*p ← 1
q← p
*q ← *p + 1
escreva(*p)
libere(p)

lixo
q
Ponteiros ou Apontadores
Exemplo 4:
Alocação dinâmica
Inteiro:*p,*q
aloque(p)
*p ← 1
q← p
*q ← *p + 1
escreva(*p)
libere(p)

p
1
q
lixo
Ponteiros ou Apontadores
Exemplo 4:
Alocação dinâmica
Inteiro:*p,*q
aloque(p)
*p ← 1
q← p
*q ← *p + 1
escreva(*p)
libere(p)

p
1
q
Ponteiros ou Apontadores
Exemplo 4:
Alocação dinâmica
Inteiro:*p,*q
aloque(p)
*p ← 1
q← p
*q ← *p + 1
escreva(*p)
libere(p)

p
2
q
Ponteiros ou Apontadores
Exemplo 4:
Alocação dinâmica
Inteiro:*p,*q
aloque(p)
*p ← 1
q← p
*q ← *p + 1
escreva(*p)
libere(p)

p
2
q
Resultado = 2
Ponteiros ou Apontadores
Exemplo 4:
Alocação dinâmica
Inteiro:*p,*q
aloque(p)
*p ← 1
q← p
*q ← *p + 1
escreva(*p)
libere(p)

Ponteiros ou Apontadores
Exemplo 4:
Alocação dinâmica
Inteiro:*p,*q
aloque(p)
*p ← 1
q← p
*q ← *p + 1
escreva(*p)
libere(p)

Para evitar accidentes
acrescente:
q ← nulo
p ← nulo
Ponteiros ou Apontadores
Exemplo 5:
Tipo reg: registro
real:valor
reg:*pont
Fim_Registro
reg:*p,*q,x,x1
x.valor ←10.5
p ←&x
x.pont ←&x1


Teste de
mesa inicial
p
lixo
q
lixo
Ponteiros ou Apontadores
Exemplo 5:
Tipo reg: registro
real:valor
reg:*pont
Fim_Registro
reg:*p,*q,x,x1
x.valor ←10.5
p ←&x
x.pont ←&x1

p
lixo
q
lixo
Ponteiros ou Apontadores
Exemplo 5:
Tipo reg: registro
real:valor
reg:*pont
Fim_Registro
reg:*p,*q,x,x1
x.valor ←10.5
p ←&x
x.pont ←&x1
x1.valor ← 0,2
q ← x.pont
x1.pont ← NULO

p
lixo
Usamos o símbolo
Para indicar que o ponteiro
aponta para nulo
Ponteiros ou Apontadores
p
escreva(*p.valor)
escreva(*q.valor)
escreva(*p.*pont.valor)
escreva(x.valor)
escreva(x.*pont.valor)
escreva(x1.valor)
Ponteiros ou Apontadores
p
escreva(*p.valor)
escreva(*q.valor)
escreva(*p.*pont.valor)
escreva(x.valor)
escreva(x.*pont.valor)
escreva(x1.valor)
10,5
0,2
0,2
10,5
0,2
0,2
Ponteiros ou Apontadores
Exercícios:
(1) Qual é a saída de c em
inteiro *p,*q,a,b,c
a ←1
b ←2
p ← &a
q ← &b
c ← *p + *q
Ponteiros ou Apontadores
Exercícios:
(2) Qual é a saída de c em
inteiro *p, **r,a,c,b
a ←1
b ←2
p ← &a
r ← &p
c ← **r + b
(3) Obtenha a saída do algoritmo anterior
fazendo com que p e q sejam alocadas
dinamicamente. Não use x nem x1.
Ponteiros ou Apontadores
Exercícios:
(4) Por que o algoritmo abaixo está errado?
procedimento troca (inteiro: *i, *j)
inteiro *temp
Início
*temp ← *i
*i ← *j
*j ← *temp
Fim
Ponteiros ou Apontadores
(5) Dado o seguinte algoritmo, complete as
Tabelas 1 e 2.
inteiro: i, j, *p_1, *p_2, **p_p_1, **p_p_2
i←4
j←5
p_1 ← &i
p_2 ← &j
p_p_1 ← &p_2
p_p_2 ← &p_1
(6)
Ponteiros ou Apontadores
Vamos criar os seguintes procedimentos:
 leCoordenada3D(Coordenada3d *f);: lê dados
de um ponto no espaço tridimensional com
coordenadas (x,y,z) passada como ponteiro.
(Por quê como ponteiro?)
 imprimeCoordenada3D(Coordenada3d f);
Imprime coordenadas de um ponto no espaço
tridimensional.
O programa principal que requeira a leitura de 5
pontos no espaço tridimensional.
(7) Refaça o exercício 6 considerando um vetor
de pontos tridimensionais de tamanho dinâmico
(use aloque).
Download