Buscar

02.LabII.Ponteiros

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 48 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 48 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 48 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

Laboratório de Programação II
Departamento de Ciência da Computação
UFJF
Aula de hoje
• Ponteiros
• Ponteiros
• Ponteiros
2
Introdução
• Cada objeto (variável, string, vetor etc.) que
reside na memória do computador ocupa um 
certo número de bytes:
– char: 1 byte
– short: 2 bytes
– int: 4 bytes
– float: 4 bytes
– double: 8 bytes
3
Introdução
• A memória de qualquer
computador é uma
sequência de bytes.
• Cada byte na memória é 
identificado por um 
endereço numérico, 
independente do seu
conteúdo.
• Muitas vezes endereços de 
memória são representados
no formato hexadecimal:
– 0x0065FD40
– 0x0065FD44 4
Introdução
• Ou seja, sempre que declaramos uma variável, temos
associados a ela:
– um nome (ou identificador)
– um endereço de memória
– um valor
• Sempre que declaramos uma
variável, o programa aloca espaço
de memória para ela e sabe
internamente aonde ela está
armazenada.
5
Endereços
• Antes de falar de ponteiros, vamos ver como
descobrir o endereço de variáveis.
• Para isso é preciso usar o operador “endereço
de”, representado por &, a uma variável para
descobrir o seu endereço.
• Se total é a variável, então &total é o seu
endereço.
6
Endereços
#include <iostream> 
using namespace std; 
int main()
{
int biscoitos = 6;
double peso = 4.5;
cout << “valor de biscoitos = “ << biscoitos ;
cout << “ e endereco de biscoitos = “;
cout << &biscoitos << endl;
cout << “valor de peso = “ << peso;
cout << “e endereco de peso = “ << &peso << endl;
return 0;
}
7
Endereços
#include <iostream> 
using namespace std; 
int main()
{
int biscoitos = 6;
double peso = 4.5;
cout << “valor de biscoitos = “ << biscoitos ;
cout << “ e endereco de biscoitos = “;
cout << &biscoitos << endl;
cout << “valor de peso = “ << peso;
cout << “e endereco de peso = “ << &peso << endl;
return 0;
}
8
Saída
valor de biscoitos: 6 e endereco de biscoitos: 0x0065FD40
valor de peso: 6 e endereco de peso: 0x0065FD44
Ponteiros
• Um ponteiro é simplesmente uma variável que
armazena o endereço de outra variável ao invés
do conteúdo desta.
• Temos assim um tipo de dado especial – o 
ponteiro – o qual armazena o endereço de um 
valor.
• O nome da variável de um tipo ponteiro
representa a posição de memória daquele valor.
• Aplicando o operador * (“conteúdo de”) 
recuperamos o valor armazenado naquela
posição de memória.
9
Ponteiros
• Isto é, se pt_x é um ponteiro, então *pt_x
é o valor naquele endereço.
• Através do operador *, podemos alterar o 
valor que está armazenado em uma posição
de memória
*pt_x = 100;
10
Ponteiros
int main()
{
int updates = 6;
int *p_updates; 
p_updates = &updates; 
// imprime valores
cout << “Valor: updates = “ << updates;
cout << “, *p_updates = “ << *p_updates << endl;
// imprime enderecos
cout << “Endereço: &updates = “ << &updates;
cout << “, p_updates = “ << p_updates << endl;
// usa ponteiro para alterar o conteudo
*p_updates = *p_updates + 1;
cout << “Valor atualizado updates = “ << updates << endl;
return 0;
}
11
Ponteiros
int main()
{
int updates = 6;
int *p_updates; 
p_updates = &updates; 
// imprime valores
cout << “Valor: updates = “ << updates;
cout << “, *p_updates = “ << *p_updates << endl;
// imprime enderecos
cout << “Endereço: &updates = “ << &updates;
cout << “, p_updates = “ << p_updates << endl;
// usa ponteiro para alterar o conteudo
*p_updates = *p_updates + 1;
cout << “Valor atualizado updates = “ << updates << endl;
return 0;
}
Saída
Valor: updates = 6 , *p_update = 6
Endereço: &updates = 0x0065FD48, p_updates = 0x0065FD48
Valor atualizado updates = 7
12
Ponteiros
• Declarando ponteiros:
• Podemos ler a declaração da seguinte forma:
• *pt_var é do tipo int
• ou
• pt_var é do tipo int* (isto é ponteiro para int)
• Podemos usar:
• Ou ainda declarar ponteiros para outros tipos:
int *pt_var;
int *pt_var;
int* pt_var;
int * pt_var;
char *pt_var1;
float *pt_var2;
double *pt_var3; 13
Usar esta 
(convenção)
Ponteiros
• Podemos declarar e inicializar um ponteiro
• o que inicializa pt_num com o endereço da 
variável numero.
• É preciso tomar cuidado ao usar variáveis do 
tipo ponteiro!
int numero = 10;
int *pt_num = &numero;
// erro
int *pt_var;
*pt_var = 2058; 
Quando declaramos uma variável do 
tipo ponteiro, espaço para armazenar 
um endereço de memória é criado, 
mas isso não significa que memória 
foi alocada para armazenar a 
informação que o ponteiro aponta.
14
Ponteiros
15
Aritmética de Ponteiros
• Somar 1 a uma variável inteira incrementa o seu valor de 
uma unidade.
• O que significa somar 1 a uma variável do tipo ponteiro?
– Depende do tipo do ponteiro.
– Nesse exemplo, a adição soma 4 ao valor numérico que 
representa o endereço contido em pt_num, pois um inteiro 
ocupa 4 bytes na memória.
– Ou seja, ao somar 1 a um ponteiro, você está indo para o 
próximo endereço de memória do tipo de dado especificado.
– Por outro lado, somar 1 a um ponteiro para double, adiciona 8 
ao valor numérico do endereço que o ponteiro armazena.
– Generalizando: 
int numero = 10;
int *pt_num = &numero;
pt_num = pt_num + 1;
16
pt_tipo = pt_tipo + tam(tipo)*n;
Aritmética de Ponteiros
int x;
int *ap;
cout << “Digite x: “;
cin >> x;
ap = &x;
cout << “Endereço de x = “ << &x;
cout << endl;
cout << “Valor de ap= “ << ap;
cout << endl;
cout << “Valor de ap+1= “ << ap+1;
cout << endl;
cout << “Valor de ap+2= “ << ap+2;
cout << endl;
Saída
Endereço de x = 0x7FFFE5B7B53C
Valor de ap = 0x7FFFE5B7B53C
Valor de ap+1 = 0x7FFFE5B7B540
Valor de ap+2 = 0x7FFFE5B7B544
17
Ponteiros e Arrays
• C++ interpreta o nome de um array como o 
endereço de memória do primeiro elemento 
do array.
int vet[3] = {10,20,30};
cout << "enderecos" << endl;
cout << vet << endl;
cout << vet+1 << endl;
cout << vet+2 << endl;
cout << "valores" << endl;
cout << vet[0] << endl << vet[1] << endl
<< vet[2] << endl;
18
Ponteiros e Arrays
19
Ponteiros e Arrays
• Ou seja, temos duas formas de acessar os 
elementos de um array:
– usando o operador []
• vet[2]
• vet[i]
– usando aritmética de ponteiros
• *(vet+2)
• *(vet+i)
20
Ponteiros e Funções
• Em C/C++ existem dois tipos de passagem de 
parâmetros para funções:
– Passagem por valor
• Uma cópia do valor é passado para a função
• Mesmo que a função altere o valor, esta alteração não 
permanecerá no parâmetro original após o retorno da 
função
– Passagem por referência
• Se a função alterar o valor do objeto passado, essa 
alteração será realizada no objeto original
21
22
void troca(int a, int b) 
{
int aux = b;
b = a;
a = aux;
}
int main()
{
int x=2, y=30;
troca(x, y);
cout << “x = “ << x << “ , “;
cout << “y = “ << y << endl;
return 0;
}
Saída
x=2 , y=30
!Errado!
Ponteiros e Funções
22
23
Ponteiros e Funções
void troca(int a, int b) 
{
int aux = b;
b = a;
a = aux;
}
int main()
{
int x=2, y=30;
troca(x, y);
cout << “x = “ << x << “ , “;
cout << “y = “ << y << endl;
return 0;
}
23
24
Ponteiros e Funções
void troca(int a, int b) 
{
int aux = b;
b = a;
a = aux;
}
int main()
{
int x=2, y=30;
troca(x, y);
cout << “x = “ << x << “ , “;
cout << “y = “ << y << endl;
return 0;
}
24
25
Ponteiros e Funções
void troca(int a, int b) 
{
int aux= b;
b = a;
a = aux;
}
int main()
{
int x=2, y=30;
troca(x, y);
cout << “x = “ << x << “ , “;
cout << “y = “ << y << endl;
return 0;
}
25
26
Ponteiros e Funções
void troca(int a, int b) 
{
int aux = b;
b = a;
a = aux;
}
int main()
{
int x=2, y=30;
troca(x, y);
cout << “x = “ << x << “ , “;
cout << “y = “ << y << endl;
return 0;
}
26
27
Ponteiros e Funções
void troca(int a, int b) 
{
int aux = b;
b = a;
a = aux;
}
int main()
{
int x=2, y=30;
troca(x, y);
cout << “x = “ << x << “ , “;
cout << “y = “ << y << endl;
return 0;
}
27
28
Ponteiros e Funções
void troca(int a, int b) 
{
int aux = b;
b = a;
a = aux;
}
int main()
{
int x=2, y=30;
troca(x, y);
cout << “x = “ << x << “ , “;
cout << “y = “ << y << endl;
return 0;
} Saída
x=2 , y=30
28
29
void troca(int *a, int *b);
Ponteiros e Funções
• Para alterar o conteúdo de uma variável 
passada para uma função como argumento é 
preciso usar passagem por referência.
• Passamos então o endereço (ponteiro) do 
objeto que desejamos que a função altere o 
conteúdo
• Na função manipulamos o conteúdo do objeto 
usando o operador * (“conteúdo de”) para 
alterar o seu valor.
• O protótipo correto da função é:
29
30
void troca(int *a, int *b)
{
int aux = *b;
*b = *a;
*a = aux;
}
int main()
{
int x=2, y=30;
troca(&x, &y);
cout << “x = “ << x << “ , “;
cout << “y = “ << y << endl;
return 0;
}
Saída
x=30 , y=2
Ponteiros e Funções
30
31
Ponteiros e Funções
void troca(int *a, int *b)
{
int aux = *b;
*b = *a;
*a = aux;
}
int main()
{
int x=2, y=30;
troca(&x, &y);
cout << “x = “ << x << “ , “;
cout << “y = “ << y << endl;
return 0;
}
31
32
Ponteiros e Funções
void troca(int *a, int *b)
{
int aux = *b;
*b = *a;
*a = aux;
}
int main()
{
int x=2, y=30;
troca(&x, &y);
cout << “x = “ << x << “ , “;
cout << “y = “ << y << endl;
return 0;
}
32
33
Ponteiros e Funções
void troca(int *a, int *b)
{
int aux = *b;
*b = *a;
*a = aux;
}
int main()
{
int x=2, y=30;
troca(&x, &y);
cout << “x = “ << x << “ , “;
cout << “y = “ << y << endl;
return 0;
}
33
34
Ponteiros e Funções
void troca(int *a, int *b)
{
int aux = *b;
*b = *a;
*a = aux;
}
int main()
{
int x=2, y=30;
troca(&x, &y);
cout << “x = “ << x << “ , “;
cout << “y = “ << y << endl;
return 0;
}
34
35
Ponteiros e Funções
void troca(int *a, int *b)
{
int aux = *b;
*b = *a;
*a = aux;
}
int main()
{
int x=2, y=30;
troca(&x, &y);
cout << “x = “ << x << “ , “;
cout << “y = “ << y << endl;
return 0;
}
35
36
void troca(int *a, int *b)
{
int aux = *b;
*b = *a;
*a = aux;
}
int main()
{
int x=2, y=30;
troca(&x, &y);
cout << “x = “ << x << “ , “;
cout << “y = “ << y << endl;
return 0;
} Saída
x=30 , y=2
OK!
Ponteiros e Funções
36
37
Ponteiros e Funções
• Como arrays são ponteiros (nome do array é 
um ponteiro para o primeiro elemento), então 
a passagem de arrays para funções é sempre 
por referência.
• Sendo assim, podemos alterar os valores dos 
elementos do array dentro da função.
• Os elementos do array não são copiados, 
apenas o endereço do primeiro elemento do 
array.
37
38 void incr_vet(int tam, int vet[])
{
int i;
for(i=0; i<tam; i++)
vet[i] = vet[i] + 1;
}
int main()
{
int v[]={10, 20, 5};
incr_vet(3, v);
cout << v[0] << endl;
cout << v[1] << endl;
cout << v[2] << endl;
return 0;
}
Ponteiros e Funções
Saída
11
21
6
38
Ponteiros e Funções
• Podemos usar os seguintes protótipos para declarar 
uma função que recebe um array:
• Todas são equivalentes, e no final das contas o que é 
passado para a função é o endereço do primeiro 
elemento do array.
• Por fim, vale lembrar que funções também podem 
retornar ponteiros. Veremos mais detalhes na próxima 
aula.
void incr_vet(int tam, int vet[]);
void incr_vet(int tam, int vet[3]);
void incr_vet(int tam, int *vet);
39
Ponteiros e structs
• Também podemos ter ponteiros para tipos de 
dados definidos pelo programador.
• Como?
struct aluno_t
{
int matricula;
int idade;
int notas[10];
char sexo;
};
typedef struct aluno_t Aluno;
Aluno a;
a.matricula = 1005;
a.idade = 23;
a.notas[0] = 60;
a.notas[1] = 86;
// …
a.sexo = ‘m’;
cout << “Idade: “;
cout << a.idade << endl;
// …
40
Ponteiros e structs
• Declaramos como um ponteiro qualquer
Aluno *pta;
• Quando temos um ponteiro para uma estrutura, 
acessamos os campos da estrutura usando o 
operador -> ao invés de usar o operador .
Aluno a;
pta = &a;
pta->matricula = 1005;
pta->idade = 23;
pta->notas[0] = 60;
pta->notas[1] = 86;
// …
pta->sexo = ‘m’;
cout << “Idade: “ << pta->idade << endl;
// … 41
Exercícios
1. Ponteiro e aritmética de ponteiro (faça com auxílio do 
computador). Se i e j são variáveis inteiras e p e q ponteiros 
para int, quais das seguintes expressões de atribuição são 
incorretas? 
a) p = &i; 
b) *q=&j; 
c) p=&*&i; 
d) i=(*&)j;
e) i=*&*&j; 
f) q=&p; 
g) i=(*p)++ + *q; 
h) if(p==i)i++;
42
Exercícios
2. Dados dois números inteiros num e div. Fazer 
uma função para calcular e retornar o quociente e o 
resto da divisão inteira de num por div. Considerar o 
seguinte protótipo:
void divisao(int num, int div, int *q, int *r);
• onde:
– num: dividendo
– div: divisor
– q: quociente
– r: resto
43
Exercícios
3. Implementar uma única função que recebe um 
vetor de números inteiros (vet) e o seu tamanho 
(tam) e 
– conte o total de elementos pares
– conte o total de elementos impares
– conte o total de elementos negativos
– e por fim, retorne verdadeiro se existirem números 
negativos no vetor, ou retorne falso, caso contrário
Considere o seguinte protótipo:
bool func(int tam, int vet[], 
int *par, int *imp,
int *neg); 44
Exercícios
4. Considere o seguinte tipo de dados para 
representar um ponto no espaço 2D:
Fazer uma função que determina se um ponto p
está dentro ou fora do retângulo definido pelo 
vértice inferior esquerdo v1 e pelo vértice superior 
direito v2. Considere o protótipo: 
bool dentroRet(Ponto *v1, Ponto *v2, Ponto *p);
struct ponto_t
{
float x;
float y;
};
typedef struct ponto_t Ponto;
45
Exercícios
(*) Ponteiro e aritmética de ponteiro (faça com auxílio do computador, 
http://inforum.insite.com.br/arquivos/17035/Ponteiros1.pdf)
• Escreva uma instrução que imprima o endereço da variável x.
• O que significa o operador asterisco em cada um dos seguintes casos: 
a) int *p; b) cout << *p; c) *p = x*5; d) cout << *(p+1);
• Assuma as declarações: int i=3, j=5; int *p = &i; *q = &j;. Indique qual o valor 
das seguintes expressões: a) p == &q; b) *q-*; c) **&p; d)3*-*p/(*q)+7;
• Qual é a saída deste programa?
#include <iostream.h>
void main( ) {
int i=5, *p;
p = &i;
cout << p << ‘\t’ << (*p+2) << ‘ \t’ << **&p << ‘\t’ << (3**p) << ‘ \t’ << (**&p+4);
}
46
Exercícios
(*) Ponteiro e aritmética de ponteiro (faça com auxílio do computador)
Qual a diferença entre: mat[3] e *(mat+3)?
O que fazem os seguintes programas:
void main( ) {
int mat[ ] = {4, 5, 6};
for(int j=0; j<3; j++)
cout << “ \n” << *(mat+j);}
void main( ){
int mat[ ] = {4, 5, 6};
for(int j=0; j<3; j++)
cout << “ \n” << (mat+j); }
void main( ) {
int mat[ ] = {4, 5, 6}; int *p=mat;
for(int j=0; j<3; j++)
cout << “ \n” << *p++;}
47
Exercícios
(*) Passagem de parâmetros por referência
• Implementar uma função que calcule as raízes de uma equação do segundo 
grau, do tipo ax2+bx+c=0. Essa função deve obedecer ao protótipo:
int raizes(float a, float b, float c, float *x1, float *x2);
Essa função deve ter como valor de retorno o número de raízes reais e distintas 
da equação. Se existirem raízes reias, seus valores devem ser armazenados nas 
variáveis apontadas por x1 e x2.
• Implementar um função que calcule a área da superfície e o volume de uma 
esfera de raio r. Essa função deve obedecer ao protótipo:
void calc_esfera(float r, float *area, float *volume);
A área da superfície e o volume são dados, respectivamente, por 4r2 e 4r3/3. 
Use a função pow(x, y) para calcular xy. Deve-se usar #include <cmath>
48

Continue navegando