Você está na página 1de 91

Ponteiros

Professora Dra. Luana Batista da Cruz


luana.batista@ufca.edu.br
Roteiro
01 Ponteiros
02 Passagem de parâmetros
03 Ponteiro para ponteiro

2
Ponteiros
01 Endereços
Memória
Simplificando a memória
Conceito de ponteiros
Ponteiros e memória
Endereços
● Quais são as características da variável x, declarada a seguir?

● Tipo: int
● Nome da variável: x
● Endereço de memória ou referência: 0061FF1C
● Valor: 10

● Para acessar o endereço de uma variável, utilizamos o operador &

4
Memória
Endereço Variável Conteúdo
00010000 ?? ??
00010001 ?? ??
00010002 ?? ??
● A memória é formada por várias
00010003 ?? ??
células
00010004 ?? ??
00010005 ?? ?? ● Cada célula contém um endereço
00010006 ?? ?? e um valor (conteúdo)
00010007 ?? ?? ● O tamanho do endereço e do valor
00010008 ?? ?? dependem da arquitetura (32/64
00010009 ?? ?? bits)
0001000A ?? ??
0001000B ?? ??
0001000C ?? ??
0001000D ?? ??
5
Memória
Endereço Variável Conteúdo
00010000 i ??
00010001 ?? ??
00010002 ?? ??
Exemplo
00010003 ?? ??
● O caractere i ocupa 1 byte na
00010004 ?? ??
memória
00010005 ?? ??
00010006 ?? ??
00010007 ?? ??
00010008 ?? ??
00010009 ?? ??
0001000A ?? ??
0001000B ?? ??
0001000C ?? ??
0001000D ?? ??
6
Memória
Endereço Variável Conteúdo
00010000
00010001
i ??
00010002
Exemplo
00010003
● O inteiro i ocupa 4 bytes na
00010004 ?? ??
memória
00010005 ?? ??
00010006 ?? ??
00010007 ?? ??
00010008 ?? ??
00010009 ?? ??
0001000A ?? ??
0001000B ?? ??
0001000C ?? ??
0001000D ?? ??
7
Memória
Endereço Variável Conteúdo
00010000
00010001
i ??
00010002
Exemplo
00010003
● O ponto flutuante i ocupa 4 bytes na
00010004 ?? ??
memória
00010005 ?? ??
00010006 ?? ??
00010007 ?? ??
00010008 ?? ??
00010009 ?? ??
0001000A ?? ??
0001000B ?? ??
0001000C ?? ??
0001000D ?? ??
8
Memória
Endereço Variável Conteúdo
00010000
00010001
00010002
Exemplo
00010003
i ?? ● O double i ocupa 8 bytes na
00010004
memória
00010005
00010006
00010007
00010008 ?? ??
00010009 ?? ??
0001000A ?? ??
0001000B ?? ??
0001000C ?? ??
0001000D ?? ??
9
Endereço Variável Conteúdo Memória
00010000 i ??
00010001
00010002
00010003
c ?? Exemplo
● Note as variáveis alocadas
00010004
00010005
00010006
f ??
00010007
00010008
00010009
0001000A
0001000B
0001000C
d ??
0001000D
0001000E
0001000F
00010010
10
de memória
Simplificar a alocação
Endereço Variável Conteúdo Endereço Variável Conteúdo
00010000 i ?? #123 int i ??
00010001 #124 char c ??
00010002 #125 float f ??
c ??
00010003 #126 double d ??
00010004 #127
00010005 #128
00010006 #129
f ??
00010007 #130
00010008 #131
00010009 #132
0001000A #133
0001000B #134
0001000C #135
d ??
0001000D #136
0001000E #137
0001000F #138
00010010 #123
11
Ponteiros
● Um ponteiro (apontador ou pointer) é um tipo especial de variável que
armazena um endereço de memória em seu conteúdo

● Ponteiros são declarados utilizando o caractere especial *:

● Variáveis podem ser declaradas em uma única linha:

12
Memória
Endereço Variável Conteúdo
00010000
Exemplo
00010001
*c ?? ● Note os quatro ponteiros
00010002
00010003
00010004
00010005
*i ??
00010006
00010007
00010008
00010009
*f ?? ● Todos requerem o mesmo tamanho
0001000A
(32/64 bits)
0001000B
0001000C ● Lembre-se: um ponteiro armazena
0001000D
um endereço de memória,
*d ?? independente do tipo
0001000E
0001000F 13
de memória
Simplificar a alocação
Endereço Variável Conteúdo Endereço Variável Conteúdo
00010000 #123 char *c ??
00010001 #124 int *i ??
*c ??
00010002 #125 float *f ??
00010003 #126 double *d ??
00010004 #127
00010005 #128
*i ??
00010006 #129
00010007 #130
00010008 #131
00010009 #132
*f ??
0001000A #133
0001000B #134
0001000C #135
0001000D #136
*d ??
0001000E #137
0001000F #138
14
Ponteiros
● Variável do tipo ponteiro
○ C permite o armazenamento e a manipulação de valores de endereços de
memória
○ Declaração usando tipo *nome_do_ponteiro

● Para cada tipo existente, há um tipo ponteiro que pode armazenar endereços de
memória onde existem valores do tipo correspondente armazenados
● Operador unário & (“endereço de”)
○ Resulta no endereço da posição de memória reservada para a variável

● Operador unário * (“conteúdo de”)


○ Acessa o conteúdo do endereço de memória armazenado pela variável ponteiro

15
Ponteiros
● O conteúdo da memória apontada por um ponteiro se refere ao valor
armazenado no endereço de memória para o qual o ponteiro aponta
○ Este conteúdo (valor) pode ser alterado usando o operador *
○ Exemplo

O que será impresso?

16
Ponteiros
● O conteúdo da memória apontada por um ponteiro se refere ao valor
armazenado no endereço de memória para o qual o ponteiro aponta
○ Este conteúdo (valor) pode ser alterado usando o operador *
○ Exemplo

O que será impresso?


y: 10

17
Ponteiros
● Exemplo

Conteúdo #500 A

Endereço #100 #500

18
Ponteiros
● Exemplo

Logo, P é um ponteiro
Conteúdo #500 A para …?

Endereço #100 #500

19
Ponteiros
● Exemplo

Logo, P é um ponteiro
Conteúdo #500 A para char?

Endereço #100 #500

P
char *P

20
Ponteiros
● Exemplo

Conteúdo #500 A

Endereço #100 #500

printf(“? = %p \n”, &p);


printf(“?? = %p \n”, p);
printf("??? = %c \n", *p);

21
Ponteiros
● Exemplo

Conteúdo #500 A

Endereço #100 #500

printf(“Endereço de P = %p \n”, &p);


printf(“Endereço que P aponta = %p \n”, p);
printf(“Conteúdo do endereço que P aponta = %c \n”, *p);
22
Ponteiros
● Exemplo

Conteúdo #500 A

Endereço #100 #500

Endereço de P = #100
Endereço que P aponta = #500
Conteúdo do endereço que P aponta = A
23
Ponteiros
● Exemplo c - #112
p - #108
a 5 #104

c - #112
p #104 #108
a 5 #104

c - #112
p #104 #108
a 6 #104

c 6 #112
p #104 #108
a 6 #104
24
Ponteiros e memória
Endereço Variável Conteúdo
#123 ?? ?? Exemplo de uso
#124 ?? ??
#125 ?? ??
#126 ?? ??
#127 ?? ??
#128 ?? ??
#129 ?? ??
#130 ?? ??
#131 ?? ??
#132 ?? ??
#133 ?? ??
#134 ?? ??
#135 ?? ??
#136 ?? ??
25
Ponteiros e memória
Endereço Variável Conteúdo
#123 int i ?? Exemplo de uso
#124 ?? ??
#125 ?? ??
#126 ?? ??
#127 ?? ??
#128 ?? ??
#129 ?? ??
#130 ?? ??
#131 ?? ??
#132 ?? ??
#133 ?? ??
● A memória para o inteiro i será
alocada
#134 ?? ??
#135 ?? ??
#136 ?? ??
26
Ponteiros e memória
Endereço Variável Conteúdo
#123 int i 15 Exemplo de uso
#124 ?? ??
#125 ?? ??
#126 ?? ??
#127 ?? ??
#128 ?? ??
#129 ?? ??
#130 ?? ??
#131 ?? ??
#132 ?? ??
#133 ?? ??
● O conteúdo de i será alterado para
15 (representação será em decimal,
#134 ?? ??
mas na prática é tudo em binário).
#135 ?? ??
#136 ?? ??
27
Ponteiros e memória
Endereço Variável Conteúdo
#123 int i 15 Exemplo de uso
#124 char c s
#125 ?? ??
#126 ?? ??
#127 ?? ??
#128 ?? ??
#129 ?? ??
#130 ?? ??
#131 ?? ??
#132 ?? ??
#133 ?? ??
● A memória para o char c será
alocada e inicializada com ʻsʼ
#134 ?? ??
#135 ?? ??
#136 ?? ??
28
Ponteiros e memória
Endereço Variável Conteúdo
#123 int i 15 Exemplo de uso
#124 char c s
#125 int *p #123
#126 ?? ??
#127 ?? ??
#128 ?? ??
#129 ?? ??
#130 ?? ??
#131 ?? ??
#132 ?? ??
#133 ?? ??
● O ponteiro de inteiro p será
declarado e inicializado com o
#134 ?? ??
endereço de memória de i
#135 ?? ??
#136 ?? ??
29
Ponteiros e memória
Endereço Variável Conteúdo
#123 int i 25 Exemplo de uso
#124 char c s
#125 int *p #123
#126 ?? ??
#127 ?? ??
#128 ?? ??
#129 ?? ??
#130 ?? ??
#131 ?? ??
#132 ?? ??
#133 ?? ??
● O conteúdo da memória apontada
por p será atualizado para 25
#134 ?? ??
#135 ?? ??
#136 ?? ??
30
Ponteiros e memória
Endereço Variável Conteúdo
#123 int i 25 Exemplo de uso
#124 char c s
#125 int *p #123
#126 ?? ??
#127 ?? ??
#128 ?? ??
#129 ?? ??
#130 ?? ??
#131 ?? ??
#132 ?? ??
#133 ?? ??
● Agora o método main será
finalizado
#134 ?? ??
#135 ?? ??
#136 ?? ??
31
Ponteiros
● Exemplo

O que será impresso?

32
Ponteiros
● Exemplo

O que será impresso?


x: 99

33
Ponteiros
● Exemplo

O que será impresso?

34
Ponteiros
● Exemplo

O que será impresso?


x: -5

35
Ponteiros
● Exemplo

O que será impresso?

36
Ponteiros
● Exemplo

O que será impresso?


x: 10

37
Ponteiros
● Exemplo

38
Ponteiros
● Exemplo

39
Passagem de parâmetros
02 Passagem de parâmetros por valor
Passagem de parâmetros por referência
Exemplo de execução
Passagem de parâmetros
● Os parâmetros formais (variáveis locais, declaradas como parâmetro da função
chamada) são inicializados com o valor dos parâmetros reais (variáveis
passadas como parâmetro)
○ Passagem por valor – o valor dos parâmetros formais, se alterados durante a
execução da função não acarretarão em nenhuma modificação no valor dos
parâmetros reais (variáveis da função chamadora)

● Observação: todos os exemplos mostrados até o momento utilizam passagem


de parâmetro por valor

41
Passagem de parâmetros por valor
● A função troca_1 deseja realizar a troca dos valores de a e b que são passados
por parâmetros
○ Qual o problema da função (troca_1) a seguir?

42
Passagem de parâmetros por valor
● Qual o problema da função (troca_1) a seguir?

● Os parâmetros são passados por valor!


● Assim, cópias de a e b são passadas para a função
● Logo: a função não efetua a troca de fato!

43
Passagem de parâmetros por valor
● Qual o problema da função (troca_1) a seguir?

● Então como alterar os valores das variáveis c e d usando função?


○ Retornar pela função?

44
Passagem de parâmetros por valor
● Qual o problema da função (troca_1) a seguir?

● Então como alterar os valores das variáveis c e d usando função?


○ Retornar pela função? Não. Porque não é possível retornar mais de um valor

45
Passagem de parâmetros por valor
● Qual o problema da função (troca_1) a seguir?

● Então como alterar os valores das variáveis c e d usando função?


○ Retornar pela função? Não. Porque não é possível retornar mais de um valor
○ Podemos alterar o valor da variável dentro da própria função!

46
Passagem de parâmetros
● Como alterar o valor da variável dentro da função?
○ Nós já utilizamos uma função que faz isso..

47
Passagem de parâmetros
● Como receber um endereço de memória na função?

● A chamada abaixo vai funcionar?

● Não. Pois a função recebe dois valores do tipo int, não dois endereços de
memória
● Para receber um endereço de memória (referência), temos que usar um ponteiro!

48
Passagem de parâmetros por referência
● A solução é utilizar ponteiros para simular a passagem por referência

● A chamada de troca_2() recebe ponteiros para os parâmetros:


○ a = &c, i.e., ponteiro a aponta para o endereço de c
○ b = &d, i.e., ponteiro b aponta para o endereço de d
● Em seguida, troca o conteúdo das memórias apontadas

49
Passagem de parâmetros por referência
● A solução é utilizar ponteiros para simular a passagem por referência

● A chamada de troca_2() recebe ponteiros para os parâmetros:


○ a = &c, i.e., ponteiro a aponta para o endereço de c
○ b = &d, i.e., ponteiro b aponta para o endereço de d
● Em seguida, troca o conteúdo das memórias apontadas

50
Exemplo de execução
Endereço Variável Conteúdo
#123
#124
#125
#126
#127
#128
#129
#130
#131
#132
#133
#134
#135
#136
51
Exemplo de execução
Endereço Variável Conteúdo
#123
#124 int x 100
main
#125 int y 200
#126
#127
#128
#129
#130
#131
#132
#133
#134
#135
#136
52
Exemplo de execução
Endereço Variável Conteúdo
#123
#124 int x 100
main
#125 int y 200
#126
#127
#128
#129
#130
#131
#132
#133
#134
#135
#136
53
Exemplo de execução
Endereço Variável Conteúdo
#123
#124 int x 100
main
#125 int y 200
#126
#127 int a 100
troca_1
#128 int b 200
#129
#130
#131
#132
#133
#134
#135
#136
54
Exemplo de execução
Endereço Variável Conteúdo
#123
#124 int x 100
main
#125 int y 200
#126
#127 int a 100
#128 int b 200 troca_1
#129 int aux 100
#130
#131
#132
#133
#134
#135
#136
55
Exemplo de execução
Endereço Variável Conteúdo
#123
#124 int x 100
main
#125 int y 200
#126
#127 int a 200
#128 int b 200 troca_1
#129 int aux 100
#130
#131
#132
#133
#134
#135
#136
56
Exemplo de execução
Endereço Variável Conteúdo
#123
#124 int x 100
main
#125 int y 200
#126
#127 int a 200
#128 int b 100 troca_1
#129 int aux 100
#130
#131
#132
#133
#134
#135
#136
57
Exemplo de execução
Endereço Variável Conteúdo
#123
#124 int x 100
main
#125 int y 200
#126
#127 int a 200
liberado
#128 int b 100
para uso
#129 int aux 100
#130
#131
#132
#133
#134
#135
#136
58
Exemplo de execução
Endereço Variável Conteúdo
#123
#124 int x 100
main
#125 int y 200
#126
#127 int a 200
liberado
#128 int b 100
para uso
#129 int aux 100
#130
#131
#132
#133
#134
#135
#136
59
Exemplo de execução
Endereço Variável Conteúdo
#123
#124 int x 100
main
#125 int y 200
#126
#127 int a 200
liberado
#128 int b 100
para uso
#129 int aux 100
#130
#131 int *a #124
troca_2
#132 int *b #125
#133
#134
#135
#136
60
Exemplo de execução
Endereço Variável Conteúdo
#123
#124 int x 100
main
#125 int y 200
#126
#127 int a 200
liberado
#128 int b 100
para uso
#129 int aux 100
#130
#131 int *a #124
#132 int *b #125 troca_2
#133 int aux 100
#134
#135
#136
61
Exemplo de execução
Endereço Variável Conteúdo
#123
#124 int x 200
main
#125 int y 200
#126
#127 int a 200
liberado
#128 int b 100
para uso
#129 int aux 100
#130
#131 int *a #124
#132 int *b #125 troca_2
#133 int aux 100
#134
#135
#136
62
Exemplo de execução
Endereço Variável Conteúdo
#123
#124 int x 200
main
#125 int y 100
#126
#127 int a 200
liberado
#128 int b 100
para uso
#129 int aux 100
#130
#131 int *a #124
#132 int *b #125 troca_2
#133 int aux 100
#134
#135
#136
63
Exemplo de execução
Endereço Variável Conteúdo
#123
#124 int x 200
main
#125 int y 100
#126
#127 int a 200
liberado
#128 int b 100
para uso
#129 int aux 100
#130
#131 int *a #124
liberado
#132 int *b #125
para uso
#133 int aux 100
#134
#135
#136
64
Passagem de parâmetros
● Passagem de parâmetros por valor
○ A função recebe uma cópia do valor da variável que é fornecida quando é
invocada. Todas as alterações feitas dentro da função não vão afetar os valores
originais

● Passagem de parâmetros por referência


○ Neste caso o que é enviado para a função é uma referência às variáveis
utilizadas, e não uma simples cópia. As alterações realizadas dentro da função
irão alterar os valores contidos nessas variáveis

65
Ponteiro para ponteiro
03 Conceito
Dentro de função
Exemplo de execução
Ponteiro para ponteiro
● Um ponteiro é uma variável que guarda o endereço de memória de uma outra
variável, ambos do mesmo tipo
Ponteiro Variável

Armazena Endereço Valor

● Um ponteiro para um ponteiro consiste em uma variável que guarda o endereço


de outro ponteiro, essa outra por sua vez guarda o endereço da variável que tem
um tipo de dado "comum"

Ponteiro Ponteiro Variável

Armazena Endereço Endereço Valor

67
Ponteiro para ponteiro
● Podemos declarar um ponteiro para um ponteiro com a seguinte notação

● Portanto
○ *nome_da_variavel é o conteúdo do ponteiro intermediário
○ **nome_da_variavel é o conteúdo final da variável apontada

68
Ponteiro para ponteiro
Endereço Variável Conteúdo
● Exemplo #123
#124
#125
#126
#127
#128
#129
#130
#131
#132
#133
#134
#135
#136
69
Ponteiro para ponteiro
Endereço Variável Conteúdo
● Exemplo #123 float pi 3.14
#124 float *p
#125 float **pp
#126
#127
#128
#129
#130
#131
#132
#133
#134
#135
#136
70
Ponteiro para ponteiro
Endereço Variável Conteúdo
● Exemplo #123 float pi 3.14
#124 float *p #123
#125 float **pp
#126
#127
#128
#129
#130
#131
#132
#133
#134
#135
#136
71
Ponteiro para ponteiro
Endereço Variável Conteúdo
● Exemplo #123 float pi 3.14
#124 float *p #123
#125 float **pp #124
#126
#127
#128
#129
#130
#131
#132
#133
#134
#135
#136
72
Ponteiro para ponteiro
Endereço Variável Conteúdo
● Exemplo #123 float pi 3.14
#124 float *p #123
#125 float **pp #124
#126
#127
#128
#129
#130
#131
#123 #132
#133
#134
#135
#136
73
Ponteiro para ponteiro
Endereço Variável Conteúdo
● Exemplo #123 float pi 3.14
#124 float *p #123
#125 float **pp #124
#126
#127
#128
#129
#130
#131
#123 #132
3.14 #133
#134
#135
#136
74
Ponteiro para ponteiro
Endereço Variável Conteúdo
● Exemplo #123 float pi 3.14
#124 float *p #123
#125 float **pp #124
#126
#127
#128
#129
#130
#131
#123 #132
3.14 #133
#124 #134
#135
#136
75
Ponteiro para ponteiro
Endereço Variável Conteúdo
● Exemplo #123 float pi 3.14
#124 float *p #123
#125 float **pp #124
#126
#127
#128
#129
#130
#131
#123 #132
3.14 #133
#124 #134
#123
#135
#136
76
Ponteiro para ponteiro
Endereço Variável Conteúdo
● Exemplo #123 float pi 3.14
#124 float *p #123
#125 float **pp #124
#126
#127
#128
#129
#130
#131
#123 #132
3.14 #133
#124 #134
#123
#135
3.14
#136
77
Ponteiro para ponteiro
Endereço Variável Conteúdo
● Exemplo em função #123 int x
#124 int *p
#125
#126
#127
#128
#129
#130
#131
#132
#133
#134
#135
#136
78
Ponteiro para ponteiro
Endereço Variável Conteúdo
● Exemplo em função #123 int x
main
#124 int *p
#125
#126
#127
#128
#129
#130
#131
#132
#133
#134
#135
#136
79
Ponteiro para ponteiro
Endereço Variável Conteúdo
● Exemplo em função #123 int x
main
#124 int *p #123
#125
#126
#127
#128
#129
#130
#131
#132
#133
#134
#135
#136
80
Ponteiro para ponteiro
Endereço Variável Conteúdo
● Exemplo em função #123 int x 100
main
#124 int *p #123
#125
#126
#127
#128
#129
#130
#131
#132
#133
#134
#135
#136
81
Ponteiro para ponteiro
Endereço Variável Conteúdo
● Exemplo em função #123 int x 100
main
#124 int *p #123
#125
#126
#127
#128
#129
#130
#131
#132
#133
Endereco de x: #123 #134
Endereco que p aponta: #123
#135
Conteudo que p aponta: 100
#136
82
Ponteiro para ponteiro
Endereço Variável Conteúdo
● Exemplo em função #123 int x 100
main
#124 int *p #123
#125
#126
#127
#128
#129
#130
#131
#132
#133
#134
#135
#136
83
Ponteiro para ponteiro
Endereço Variável Conteúdo
● Exemplo em função #123 int x 100
main
#124 int *p #123
#125
mudar_
#126 int **a #124
conteudo
#127
#128
#129
#130
#131
#132
#133
#134
#135
#136
84
Ponteiro para ponteiro
Endereço Variável Conteúdo
● Exemplo em função #123 int x 200
main
#124 int *p #123
#125
mudar_
#126 int **a #124
conteudo
#127
#128
#129
#130
#131
#132
#133
#134
#135
#136
85
Ponteiro para ponteiro
Endereço Variável Conteúdo
● Exemplo em função #123 int x 200
main
#124 int *p #123
#125
mudar_
#126 int **a #124
conteudo
#127

Endereco que a aponta: #124 #128


Endereco do end. que a aponta: #123 #129
Conteudo do end. que a aponta: 200
#130
#131
#132
#133
#134
#135
#136
86
Ponteiro para ponteiro
Endereço Variável Conteúdo
● Exemplo em função #123 int x 200
main
#124 int *p #123
#125
liberado
#126 int **a #124
para uso
#127
#128
#129
#130
#131
#132
#133
#134
#135
#136
87
Ponteiro para ponteiro
Endereço Variável Conteúdo
● Exemplo em função #123 int x 200
main
#124 int *p #123
#125
liberado
#126 int **a #124
para uso
#127
#128
#129
#130
#131
#132
#133
#134
#135
Novo conteudo que p aponta: 200
#136
88
Por que usar ponteiros?
● Ponteiros são muito úteis quando uma variável tem que ser acessada em
diferentes partes de um programa. Neste caso, o código pode ter vários
ponteiros espalhados por diversas partes do programa, “apontando” para a
variável que contém o dado desejado. Caso este dado seja alterado, não há
problema algum, pois todas as partes do programa tem um ponteiro que aponta
para o endereço onde reside o dado atualizado

● Existem várias situações onde ponteiros são úteis, por exemplo


○ Alocação dinâmica de memória
○ Manipulação de vetores
○ Para retornar mais de um valor em uma função
○ Referência para listas, pilhas, árvores e grafos

89
Resumindo..
● Endereços e memória
● Conceito de ponteiros
● Ponteiros e memória
● Passagem de parâmetros por valor
● Passagem de parâmetros por referência
● Ponteiro para ponteiro
● Exemplos de execução

90
Referências

PIVA, D. J. et al. Algoritmos e programação de SCHILDT, Herbert. C completo e total. Makron, 1997.
computadores. Rio de Janeiro, RJ: Elsevier,
2012.
91

Você também pode gostar