Escolar Documentos
Profissional Documentos
Cultura Documentos
SINF0064 – Programação II
Prof. Dr. Alcides Xavier Benicasa
alcides@ufs.br
Roteiro
Noções de referências/ponteiros.
Ponteiros
• Variáveis ponteiro
• Ponteiros e Funções
2/102
1
Noções de
referências/ponteiros
Ponteiros
Definição de ponteiro:
Endereço de memória para uma variável
Memória:
A memória é dividida em posições numeradas,
podendo ser endereços usados como nomes para
variáveis
4/102
2
Variáveis Ponteiro
Exemplo:
double *p;
p é declarado como um ‘ponteiro para a variável
double
Pode-se armazenar ponteiros para variável de tipo
double
Não para outros tipos!
5/102
6/102
3
Apontar
Terminologia e visão
Fale em ‘apontar’, não em ‘endereços’
Variável ponteiro ‘aponta para’ a variável comum
7/102
Apontar para …
Operador, &
Diz respeito ao ‘endereço da’ variável
Lê-se:
“p1 é igual ao endereço de v1”
ou “p1 aponta para v1”
8/102
4
Operadores * e &
Lembre-se:
int *p1, *p2, v1, v2;
p1 = &v1;
Operador de desreferenciação, *
Considere:
int *p1, v1;
v1 = 0;
p1 = &v1;
*p1 = 42;
printf("%i\n",v1);
printf("%i\n",*p1);
10/102
5
Operador &
11/102
Ponteiro: Atribuições
12/102
6
Gráfico de Atribuição de Ponteiros
13/102
O operador malloc
7
O Operador mallocCPuro
p1 = malloc (sizeof(int));
Cria uma variável nova ‘sem nome’ e atribui à p1 que
passa a ‘apontar para’ ela
Pode-se acessar com *p1
• O uso é exatamente igual às variáveis simples
15/102
16/102
8
Exemplo de Ponteiros – Exemplo 01 CPuro
17/102
18/102
9
C++
O operador new
O Operador new
p1 = new int;
Cria uma variável nova ‘sem nome’ e atribui à p1 que
passa a ‘apontar para’ ela
Pode-se acessar com *p1
• O uso é exatamente igual às variáveis simples
20/102
10
Exemplo de Ponteiros – Exemplo 01 C/C++
21/102
22/102
11
Exemplo de Ponteiros – Exemplo 01 C/C++ (cont.)
23/102
24/102
12
C/C++
Ponteiros e Funções
Ponteiros e Funções
Exemplo:
int* encontreOutroPonteiro(int* p);
Esta declaração de função:
• Tem um ‘ponteiro para um’ parâmetro int
• Retorna ‘ponteiro para uma’ variável int
26/102
13
Exemplo de Ponteiros – Exemplo 02 CPuro
27/102
28/102
14
Manipulações Básicas de Ponteiro: Gráfico
(h)
(j)
p1 = encontreOutroPonteiro(p2);
int *p3 = malloc (sizeof(int));
int* encontreOutroPonteiro(int* p)
*p3 = 50;
p p
p1 88 p1 88
p2 53 p2 10
p3 50
(i)
*p = 10; (k)
return p3;
p p1 = encontreOutroPonteiro(p2);
p1 88 p1 10
p2 10 p2 50
29/102
Alocação Dinâmica
de Memória
15
Alocação Dinâmica de Memória
Uso da memória:
Memória
Estática
Código do Programa
Variáveis Globais e
Variáveis Estáticas
Variáveis Alocadas
Dinâmica
Memória
Dinâmicamente
(Memória Livre)
Variáveis Locais
(Pilha de Execução)
31/89
Uso da memória:
32/102
16
Alocação Dinâmica de Memória
Alocação Dinâmica:
33/102
Uso da memória:
alocação dinâmica de memória:
• usa a memória livre
• se o espaço de memória livre for menor que o espaço
requisitado, a alocação não é feita e o programa pode prever
tratamento de erro
pilha de execução:
• utilizada para alocar memória quando ocorre chamada de
função:
– sistema reserva o espaço para as variáveis locais da função
– quando a função termina, espaço é liberado (desempilhado)
34/89
17
Alocação Dinâmica de Memória - Exemplo
int *p1;
p1 = new int;
Código do Programa
*p1 = 42;
int *p2; Variáveis Globais e
p2 = p1; Variáveis Estáticas
*p2 = 33;
p1 = new int; Variáveis Alocadas
Dinâmicamente
*p1 = 50; (Memória Livre)
Variáveis Locais
(Pilha de Execução)
35/102
p1 = new int;
*p1 = 50;
pilha
p1 ?
36/102
18
Alocação Dinâmica de Memória - Exemplo
int *p1;
p1 = new int;
*p1 = 42;
int *p2;
p2 = p1;
*p2 = 33;
memória livre
?
p1 = new int; 500
*p1 = 50;
pilha
p1 500
37/102
42
p1 = new int; 500
*p1 = 50;
pilha
p1 500
38/102
19
Alocação Dinâmica de Memória - Exemplo
int *p1;
p1 = new int;
*p1 = 42;
int *p2;
p2 = p1;
*p2 = 33;
memória livre
42
p1 = new int; 500
*p1 = 50;
pilha
p2 ?
p1 500
39/102
42
p1 = new int; 500
*p1 = 50;
pilha
p2 500
p1 500
40/102
20
Alocação Dinâmica de Memória - Exemplo
int *p1;
p1 = new int;
*p1 = 42;
int *p2;
p2 = p1;
*p2 = 33;
memória livre
33
p1 = new int; 500
*p1 = 50;
pilha
p2 500
p1 500
41/102
33
p1 = new int; ? 500
700
*p1 = 50;
pilha
p2 500
p1 700
42/102
21
Alocação Dinâmica de Memória - Exemplo
int *p1;
p1 = new int
*p1 = 42
int *p2;
p2 = p1;
*p2 = 33;
memória livre
33
p1 = new int; 50 500
700
*p1 = 50;
pilha
p2 500
p1 700
43/102
Compiladores antigos:
Testam se NULL foi retornado pela chamada a new:
int *p;
p = new int;
if (p = = NULL)
{
cout << "Erro: Memória insuficiente.\n";
exit(1);
}
//Se new foi bem-sucedido, o programa
//continua a partir daqui.
44/102
22
new Bem-sucedida – Compilador Novo
45/102
Geralmente é grande
A maioria dos programas não utilizarão toda a
memória
Gerenciamento de Memória
Ainda é uma boa prática
Princípio sólido de Engenharia de Software
A memória é finita
• independente de quanto se tenha!
46/102
23
Operador delete
Exemplo:
int *p;
p = new int(5);
… //processando…
delete p;
47/102
int *p1;
p1 = new int
*p1 = 42
int *p2;
p2 = p1;
*p2 = 33;
memória livre
33
p1 = new int; 50 500
700
*p1 = 50;
delete p2;
delete p1;
pilha
p2 500
p1 700
48/102
24
Alocação Dinâmica de Memória – Exemplo (cont.)
int *p1;
p1 = new int
*p1 = 42
int *p2;
p2 = p1;
*p2 = 33;
memória livre
33
p1 = new int; 50 500
700
*p1 = 50;
delete p2;
delete p1;
pilha
p2 500
p1 700
49/102
int *p1;
p1 = new int
*p1 = 42
int *p2;
p2 = p1;
*p2 = 33;
memória livre
p1 = new int; 50
700
*p1 = 50;
delete p2;
delete p1;
pilha
p2 500
p1 700
50/102
25
Alocação Dinâmica de Memória – Exemplo (cont.)
int *p1;
p1 = new int
*p1 = 42
int *p2;
p2 = p1;
*p2 = 33;
memória livre
p1 = new int;
*p1 = 50;
delete p2;
delete p1;
pilha
p2 500
p1 700
51/102
Ponteiros Oscilantes
26
Ponteiros Oscilantes
delete p;
Destrói a variável dinâmica
mas p ainda aponta para lá!
• Chamado ‘Ponteiro Oscilante’
Se p for então desreferenciado (*p)
• Resultados serão imprevisíveis!
• Freqüentemente desastrosos!
53/102
int *p1;
p1 = new int
*p1 = 42
int *p2;
p2 = p1;
*p2 = 33;
memória livre
p1 = new int;
*p1 = 50;
delete p2;
delete p1;
pilha
p2 500
p1 = NULL; p1 700
p2 = NULL;
54/102
27
Alocação Dinâmica de Memória – Exemplo (cont.)
int *p1;
p1 = new int
*p1 = 42
int *p2;
p2 = p1;
*p2 = 33;
memória livre
p1 = new int;
*p1 = 50;
delete p2;
delete p1;
pilha
p2 500
p1 = NULL; p1 NULL
p2 = NULL;
55/102
int *p1;
p1 = new int
*p1 = 42
int *p2;
p2 = p1;
*p2 = 33;
memória livre
p1 = new int;
*p1 = 50;
delete p2;
delete p1;
pilha
p2 NULL
p1 = NULL; p1 NULL
p2 = NULL;
56/102
28
Variáveis Dinâmicas e Automáticas
Variáveis Dinâmicas
Criadas com o operador new
Criadas e destruídas durante a execução do
programa
Variáveis locais
Declaradas dentro de uma definição de função
Não-dinâmicas
• Criadas quando a função é chamada
• Destruídas quando a chamada de função é completada.
• Geralmente são chamadas de variáveis ‘automáticas’
• Propriedades controladas por você
57/102
29
Definindo Tipos Ponteiro
59/102
4. int main( )
5. {
6. setlocale (LC_ALL,"portuguese");
7. int tmp,a,b;
15. cout << "Depois da troca, primeiro número é " << a << " e o
segundo é " << b << endl;
16. return 0;
17. }
60/102
30
Exemplo de Ponteiros – Exemplo 03 C/C++ - Otimizando...
1. #include <iostream>
2. #include <locale.h>
3. using std::cout; using std::cin; using std::endl;
4. int main( )
5. {
6. setlocale (LC_ALL,"portuguese");
7. int a,b;
8. cout << "Informe o primeiro número: " << endl;
9. cin >> a;
10. cout << "Informe o segundo número: " << endl;
11. cin >> b;
17. cout << "Depois da troca, primeiro número é " << a << " e o
segundo é " << b << endl;
18. return 0;
19. }
61/102
Vetores Dinâmicos
31
Vetores Dinâmicos
Variáveis vetores
Na verdade são variáveis ponteiros!
Vetor-padrão
Tamanho fixo
Vetor dinâmico
Tamanho não especificado quando se escreve o
programa
Determinado enquanto o programa é executado
63/102
Variáveis vetores
Exemplo:
int a[10];
int *p;
a e p são ambas variáveis ponteiro!
64/102
32
Variáveis Vetor Ponteiros
Podem atribuir:
p = a; // legal.
p agora aponta para onde a aponta
• Para 1a variável indexada do vetor a
a = p; // ilegal!
65/102
Variável vetor:
int a[10];
Porém, a variável a não é do tipo int*
E sim, “const int*”
66/102
33
Exemplo de Ponteiros – Exemplo 04 C/C++
#include <iostream>
using std::cout;
using std::endl;
typedef int* IntPtr;
int main( ) {
IntPtr p;
int a[10];
int index;
p = a;
Vetores Dinâmicos
Vetores Dinâmicos
Podem crescer e encolher conforme a necessidade
68/102
34
Criando Vetores Dinâmicos
Muito simples!
Exemplo:
typedef double* DoublePtr;
DoublePtr d;
d = new double[10];
Cria a variável vetor dinamicamente alocada d,
com dez elementos, tipo-base double
69/102
Novamente Simples!
Lembre-se do Exemplo:
d = new double[10];
… //Processando
delete [] d;
Desaloca toda a memória para o vetor dinâmico
Os colchetes indicam que o ‘vetor’ existe
Lembre-se: d ainda aponta para lá!
Deve-se fixar d = NULL;
70/102
35
Exemplo de Ponteiros – Exemplo 05 C/C++
#include <iostream>
using std::cin;
using std::cout;
int main( ) {
cout << "Este programa efetua uma busca em uma lista de números.\n";
int arraySize;
cout << "Quantos números haverá na lista? ";
cin >> arraySize;
IntPtr a;
a = new int[arraySize];
fillArray(a, arraySize);
int target;
cout << "Digite um valor a ser procurado: ";
cin >> target;
int location = search(a, arraySize, target);
if (location == -1)
cout << target << " não está no vetor.\n";
else
cout << target << " é o elemento " << location << " no vetor.\n";
delete [] a;
return 0;
} 71/102
//...
36
Funções que retornam um vetor
Exemplo:
int[] umaFuncao( ); //ILEGAL
73/102
int i;
cout << "Vetor a:\n";
for (i = 0; i < 5; i++)
cout << a[i] << " ";
cout << endl;
37
Aritmética de Ponteiros
Aritmética de ‘endereços’
Exemplo:
typedef double* DoublePtr;
DoublePtr d;
d = new double[10];
d contém o endereço de d[0]
d + 1 calcula o endereço de d[1]
d + 2 calcula o endereço de d[2]
75/102
Equivale a:
for (int i = 0; i < tamanhoDoVetor; i++)
cout << d[i] << " ";
76/102
38
Vetores Dinâmicos Multidimensionais
77/102
int main( ) {
int d1, d2;
cout << "Informe as dimensões linha e a coluna do vetor:\n";
cin >> d1 >> d2;
39
Alocação Dinâmica de Memória – Bidimensionais
memória livre
pilha
79/102
a 111
80/102
40
Alocação Dinâmica de Memória – Bidimensionais
memória livre
pilha
a 111
81/102
p ?
a 111
82/102
41
Alocação Dinâmica de Memória – Bidimensionais
memória livre
pilha
p 111
a 111
83/102
p[2] = 9;
pilha
p 111
a 111
84/102
42
Alocação Dinâmica de Memória – Bidimensionais
p = a; 1
2
4
9
memória livre
p[2] = 9;
p = new int[3];
pilha
p 222
a 111
85/102
p = a; 1
2
4
9
memória livre
p[2] = 9;
p = new int[3];
p[0]=8;p[1]=1;p[2]=32;
pilha
p 222
a 111
86/102
43
Alocação Dinâmica de Memória – Bidimensionais
p = a; 1
2
4
9
memória livre
p[2] = 9;
p = new int[3];
p[0]=8;p[1]=1;p[2]=32;
IntPtr* m;
pilha
m ?
p 222
a 111
87/102
p = a; 1
2
4
9
memória livre
p[2] = 9;
p = new int[3];
p[0]=8;p[1]=1;p[2]=32;
333
IntPtr* m; 0 ?
1 ?
m = new IntPtr[2];
pilha
m 333
p 222
a 111
88/102
44
Alocação Dinâmica de Memória – Bidimensionais
p = a; 1
2
4
9
memória livre
p[2] = 9;
p = new int[3];
p[0]=8;p[1]=1;p[2]=32;
333
IntPtr* m; 0 111
1 222
m = new IntPtr[2];
m[0] = a; m[1] = p;
pilha
m 333
p 222
a 111
89/102
p = a; 1
2
4
9
memória livre
p[2] = 9;
p = new int[3];
p[0]=8;p[1]=1;p[2]=32;
333
IntPtr* m; 0 111
1 222
m = new IntPtr[2];
m[0] = a; m[1] = p;
pilha
m 333
p 222
a 111
90/102
45
Alocação Dinâmica de Memória – Bidimensionais
p = a; 1
2
4
68
memória livre
p[2] = 9;
p = new int[3];
p[0]=8;p[1]=1;p[2]=32;
333
IntPtr* m; 0 111
1 222
m = new IntPtr[2];
m[0] = a; m[1] = p;
pilha
m 333
p 222
m[0][2] = 68; a 111
91/102
222
0 8
1 1
111
2 32
0 1
1 4
2 68
memória livre
333
0 111
1 222
pilha
m 333
p 222
a 111
92/102
46
Exemplo de Ponteiros – Exemplo 08 C/C++
#include <iostream> #include <stdio.h>
typedef int* IntPtr;
int main( )
{
int a[3];
a[0]=1;
a[1]=4;
a[2]=3;
IntPtr p;
p = a;
printf("[%i,%i,%i]\n",a[0],a[1],a[2]); printf("[%i,%i,%i]\n",p[0],p[1],p[2]);
p[2] = 9;
printf("\n[%i,%i,%i]\n",a[0],a[1],a[2]); printf("[%i,%i,%i]\n",p[0],p[1],p[2]);
p = new int[3];
p[0]=8; p[1]=1; p[2]=32;
printf("\n[%i,%i,%i]\n",a[0],a[1],a[2]); printf("[%i,%i,%i]\n\n",p[0],p[1],p[2]);
IntPtr* m;
m = new IntPtr[2];
m[0] = a; m[1] = p;
for (int i=0; i<2; i++)
printf("[%i,%i,%i]\n",m[i][0],m[i][1],m[i][2]);
m[0][2] = 68;
for (int i=0; i<2; i++)
printf("[%i,%i,%i]\n",m[i][0],m[i][1],m[i][2]);
printf("\n[%i,%i,%i]\n",a[0],a[1],a[2]); printf("[%i,%i,%i]\n",p[0],p[1],p[2]);
94/102
47
Alocação Dinâmica de Memória – Bidimensionais
memória livre
333
0 111
1 222
pilha
m 333
p 222
a 111
95/102
m[0]
333
0 111
1 222
pilha
m 333
p 222
a 111
96/102
48
Alocação Dinâmica de Memória – Bidimensionais
memória livre
m[1]
333
0 111
1 222
pilha
m 333
p 222
a 111
97/102
333
0 111
1 222
pilha
m 333
p 222
a 111
98/102
49
Alocação Dinâmica de Memória – Bidimensionais
m = NULL; 0
1
1
4
2 3
memória livre
pilha
m NULL
p 222
a 111
99/102
m = NULL; 0
1
1
4
p = NULL; 2 3
memória livre
pilha
m NULL
p NULL
a 111
100/102
50
Alocação Dinâmica de Memória – Bidimensionais
111
0 1
1 4
2 3
memória livre
pilha
m NULL
p NULL
a 111
101/102
Referências
Agradecimentos:
Notas de Aula de Gustavo e Luiz Felipe Sotero do curso de
C/C++ do CIn.
102/102
51