Você está na página 1de 56

CEUB – FATECS

Bacharelado em Ciência da Computação - BCC

Estrutura de Dados

Ponteiros
Apontador (ponteiro)

• É uma célula que guarda um ENDEREÇO DE MEMÓRIA

• Analogia

• Os int guardam inteiros;


• Os float guardam número de ponto flutuante;
• Os char guardam caracteres;
• Os ponteiros guardam endereço de memória;

16/09/2023 Ponteiros 2
Ponteiros

• O uso descuidado de ponteiros pode levar a sérios bugs e a dores


de cabeça terríveis.

• Ponteiros selvagens:

• São ponteiros que não foram inicializados, eles podem provocar uma quebra
no sistema (crash)

16/09/2023 Ponteiros 3
Ponteiros

• O operador (*):
• Obtém o VALOR armazenado em um ENDEREÇO DE MEMÓRIA, e
• Também sinaliza o ponteiro na declaração de variáveis

• O operador (&)
• Obtém o ENDEREÇO DE MEMÓRIA de uma variável

16/09/2023 Ponteiros 4
Ponteiros

• Ponteiros também tem tipo

• Ao declarar ponteiros se faz necessário informar ao compilador para


que tipo de variável ele irá apontar

• Exemplo:

• Um ponteiro int aponta para um inteiro, isto é, guarda o endereço de uma


variável inteiro

16/09/2023 Ponteiros 5
ponteiros

• Declaração de ponteiros:
• int *pt; // ponteiro para inteiro
• char *temp,*pt2; //ponteiros para caracteres

• É o asterisco (*) que faz o compilador saber que aquela variável não
vai guardar um valor mas sim um endereço de memória para aquele
tipo especificado

• * operador unário pré-fixado

16/09/2023 Ponteiros 6
Ponteiros

int main()
{
int i, *p;
i = 10;
p = &i;

printf("Valor armazenado no end. que p aponta\n");


printf("%d", *p);
printf("\nEndereco da variavel i\n %p", p);
printf("\nEndereco da viariavel i\n %p", &i);
printf("\nEndereco do ponteiro p\n %p", &p);

return 0;
}

16/09/2023 Ponteiros 7
Inicialização de Ponteiro

• Para atribuir um valor a um ponteiro recém-criado poderíamos


igualá-lo a um valor de memória;

• Mas, como saber a posição na memória de uma variável do nosso


programa?

• Seria muito difícil saber o endereço de cada variável que usamos,


mesmo porque estes endereços são determinados pelo compilador
na hora da compilação e realocados na execução

16/09/2023 Ponteiros 8
Inicialização de Ponteiro

• Então, deixemos que o compilador faça este trabalho por nós;

• Exemplo de uma inicialização:


• int count=10;
• int *pt;

count
pt = &count;
pt 10

16/09/2023 Ponteiros 9
Inicialização de ponteiro
• O que acontece se fizermos:
• pt = &count
• printf(“%d”, *pt) // 10
• *pt = 12;

count
Antes pt 10

count
Depois pt 12

*pt = 12  count = 12

16/09/2023 Ponteiros 10
Atribuição de ponteiro

int main(){
int num,*p;
num=55;

p=# //obtém endereço de num (inicialização)


printf ("\nValor inicial: %d\n",num);

*p=100; //Muda o valor de num de uma maneira indireta


printf ("\nValor final: %d\n",num);

return 0;
}

16/09/2023 Ponteiros 11
Atribuição de ponteiro

16/09/2023 Ponteiros 12
Atribuição de ponteiro

int main(){
int num,valor;
int *p;
num=55;
p=# //obtém endereço de num
valor=*p; //recebe o valor que está no endereço de p
// Equivalente a: valor = num

printf ("Endereco para onde o ponteiro aponta: %p\n",p);


printf ("Endereco da variável num: %p\n",&num);
printf ("Valor da variavel apontada: %d\n", *p);
printf ("Valor: %d\n",valor);

return 0;
}
16/09/2023 Ponteiros 13
Atribuição de ponteiro

16/09/2023 Ponteiros 14
Aritmética de ponteiro

• Podemos fazer algumas operações aritméticas com ponteiros

• A primeira, e mais simples, é igualar dois ponteiros

• p1=p2
• Dessa forma, fazemos com que p1 aponte para o mesmo lugar que p2

16/09/2023 Ponteiros 15
Aritmética de ponteiro
• p2 = &count
• P1 = &count_1
• p1=p2

count
p2 10

count_1
p1 100

16/09/2023 Ponteiros 16
Aritmética de ponteiro

• Se quisermos que a variável apontada por p1 tenha o mesmo


conteúdo da variável apontada por p2 devemos fazer:
• *p1=*p2

• Basicamente,
• Depois que se aprende a usar os dois operadores (& e *) fica fácil
entender operações com ponteiros

16/09/2023 Ponteiros 17
Aritmética de ponteiro

• Operações de Incremento e Decremento


• incrementar um ponteiro é fazer ele apontar para o próximo valor do mesmo
tipo dele;

• Se temos um ponteiro para um inteiro e o incrementamos, então ele passa


a apontar para o próximo inteiro;

• É uma das razões pela qual o compilador precisa saber o tipo de um ponteiro

• Se o incremento é em um ponteiro char*, logo andará 1 byte na


memória;
• Se o incremento é em um ponteiro double* ele anda 8 bytes na
memória;

16/09/2023 Ponteiros 18
Aritmética de ponteiro

• Operações de Incremento e Decremento


• O decremento funciona semelhantemente
• p++;
• p--;

• Lembrando que estamos estudando operações com ponteiros e não de


operações com o conteúdo das variáveis para as quais eles apontam!

• Para incrementar o conteúdo da variável apontada pelo ponteiro p, faz-se:


• (*p)++;

16/09/2023 Ponteiros 19
Aritmética de ponteiro

• Existem apenas duas operações aritméticas que podem ser usadas com
ponteiros:
• Adição e Subtração

• Exemplos:
• Supomos que queremos incrementar um ponteiro de 15. Basta fazer:
• p = p + 15;
• p += 15;
• Para obter o conteúdo do ponteiro 15 posições adiante:
• *(p+15);

• A subtração funciona da mesma maneira!

16/09/2023 Ponteiros 20
Aritmética de ponteiro

• Operações entre ponteiros

• Há entretanto operações que não podem ser efetuadas num ponteiro.


• Tais como:

• Não pode dividir ou multiplicar ponteiros


• Adicionar dois ponteiros,
• Adicionar ou subtrair float ou double de ponteiros

16/09/2023 Ponteiros 21
Comparação entre dois ponteiros

• Em primeiro lugar, podemos saber se dois ponteiros são iguais ou


diferentes
• == (p==q)
• != (p!=q)

• No caso de operações do tipo >, <, >= e <= estamos comparando qual
ponteiro aponta para uma posição mais alta na memória
• p1>p2

16/09/2023 Ponteiros 22
Inicialização de arrays

int main (){ int main (){


float vet [10]; float *p, vet[10];
int i; int i;
p = &vet[0];
for (i=0;i<10;i++) for (i=0;i<10;i++){
vet[i]=0.0; *p=0.0;
p++;
... }
} ...
}
16/09/2023 Ponteiros 23
Inicialização de arrays

int main (){ int main (){


float vet [10]; float *p, vet [10];
int i; int i;
... ...
for (i=0;i<10;i++) p = vet;
printf(“%.1f”, for (i=0;i<10;i++){
vet[i]); printf(“%.1f\n”, *p);
p++;
return(0); }
} return(0);
16/09/2023 }
Ponteiros 24
Observações

int vetor[10];
int *ponteiro, i;
ponteiro = &i;

//As operações a seguir são inválidas:

vetor = vetor + 2; //erro de sintaxe


vetor++; //erro de sintaxe
vetor = ponteiro; //Tipos incompatíveis

16/09/2023 Ponteiros 25
observações

// O nome de um vetor é um ponteiro constante


// Podemos indexar o nome de um vetor

int vetor[10] = {0,1,2,3,4,5,6,7,8,9};


int *ponteiro, i;
/* As operações abaixo são válidas */
ponteiro = vetor;
//ponteiro guarda o endereço do 10 elemento do vetor
printf(“1º elemento %d\n", *ponteiro);
ponteiro = vetor+2; //recebe o end. do 3° elem.
printf(“3º elemento %d\n", *ponteiro);

16/09/2023 Ponteiros 26
observações

16/09/2023 Ponteiros 27
observações

• O nome de um vetor é um ponteiro constante

• Podemos indexar o nome de um vetor

• Como consequência podemos também indexar um ponteiro qualquer;

16/09/2023 Ponteiros 28
observações

int main (){


int vet[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int *p;
p = &vet[0]; //guarda o end. do 10 elem. do vetor
printf ("O terceiro elem. do vetor e: %d\n",p[2]);
printf ("O terceiro elem. do vetor e: %d\n",*(p+2));
return(0);
}

p[2]  *(p+2)

16/09/2023 Ponteiros 29
observações

16/09/2023 Ponteiros 30
exemplos DE FIXAÇÃO
Programa 1

Programa 1 para resolver as Tabelas 1 e 2


int main(){
int 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;
return 0;
}
16/09/2023 Ponteiros 32
Tabela 1

p_1 = &i;

1000

16/09/2023 Ponteiros 33
Verificação em Linguagem C:
//Imprimindo o end na base hexadecimal
printf("valor &i = %p, valor de p_1 = %p\n", &i, p_1);
//Imprimindo o end na base decimal
printf("valor &i = %d, valor de p_1 = %d\n ", &i, p_1);

16/09/2023 Ponteiros 34
Tabela 1

p_2 = &j;

1000 1007

16/09/2023 Ponteiros 35
Verificação em Linguagem C:
//Imprimindo o end na base hexadecimal
printf("valor &j = %p, valor de p_2 = %p\n", &j, p_2);
//Imprimindo o end na base decimal
printf("valor &j = %d, valor de p_2 = %d\n ", &j, p_2);

16/09/2023 Ponteiros 36
Tabela 1
p_2 = &j;
p_p_1 = &p_2;
Obs.: **p_p_1 é um ponteiro de ponteiro

1000 1007 1053

16/09/2023 Ponteiros 37
Verificação em Linguagem C:
//Imprimindo o end na base hexadecimal
printf(" valor &p_2 = %p, valor de p_p_1 = %p\n", &p_2, p_p_1);
//Imprimindo o end na base decimal
printf(" valor &p_2 = %d, valor de p_p_1 = %d\n\n", &p_2, p_p_1);

16/09/2023 Ponteiros 38
Tabela 1

p_p_2 = &p_1;
Obs.: **p_p_2 é um ponteiro de ponteiro

1000 1007 1053 1030

16/09/2023 Ponteiros 39
Verificação em Linguagem C:
//Imprimindo o end na base hexadecimal
printf(" valor &p_1 = %p, valor de p_p_2 = %p\n", &p_1, p_p_2);
//Imprimindo o end na base decimal
printf(" valor &p_1 = %d, valor de p_p_2 = %d\n\n", &p_1, p_p_2);

16/09/2023 Ponteiros 40
Tabela 2

j = 5;
p_2 = &j;

4 5

p_2 j

End: 1007 Valor: 5

End: 1053 End: 1007


16/09/2023 Ponteiros 41
Verificação em Linguagem C:
Printf("Imprimindo o valor referenciado\n");
printf("valor j = %d, valor de *p_2 = %d\n\n", j, *p_2);

16/09/2023 Ponteiros 42
Tabela 2

4 5 1000 1053 5

p_p_1 p_2 int j

End p_2: 1053 End: 1007 Valor: 5


End: 1071
End: 1053 End: 1007

p_p_1 = 1053
*p_p_1 = 1007
**p_p_1 = 5
16/09/2023 Ponteiros 43
Verificação em Linguagem C:
//Imprimindo o valor o valor de **p_p_1

printf("\nValor de p_p_1: %p", p_p_1);


printf("\nValor de *p_p_1: %p", *p_p_1);
printf("valor j = %d, valor de **p_p_1 = %d\n\n", j, **p_p_1);

16/09/2023 Ponteiros 44
Tabela 2

4 5 1000 1053 5 1000

p_p_2 p_1 int i

End p_1: 1030 End: 1000 Valor: 4


End: 1079
End: 1030 End: 1000

p_p_2 = 1030
*p_p_2 = 1000
**p_p_2 = 4
16/09/2023 Ponteiros 45
Verificação em Linguagem C:
printf("\n Imprimindo o endereco na base hexadecimal \n");
printf("valor p_1 = %p, valor de *p_p_2 = %p\n", p_1, *p_p_2);
printf("\n Imprimindo o endereco na base decimal \n");
printf("valor p_1 = %d, valor de *p_p_2 = %d\n\n", p_1, *p_p_2);

16/09/2023 Ponteiros 46
Tabela 2

4 5 1000 1053 5 1000 1000

p_1 int i

End: 1000 Valor: 4

End: 1030 End: 1000

p_1 = 1000
*p_1 = 4
&*p_1 = 1000
16/09/2023 Ponteiros 47
Verificação em Linguagem C:
printf("\n Imprimindo o endereco na base hexadecimal \n");
printf("valor &i = %p, valor de &*p_1 = %p\n\n", &i, &*p_1);

16/09/2023 Ponteiros 48
Tabela 2

4 5 1000 1053 5 1000 1000 5 4

p_1 int i

End: 1000 Valor: 4

End: 1030 End: 1000

p_1 = 1000
*p_1 = 4

16/09/2023 Ponteiros 49
Tabela 2

4 5 1000 1053 5 1000 1000 5 4 1000

p_1 int i

End: 1000 Valor: 4

End: 1030 End: 1000

&p_1 = 1030
*&p_1 = 1000

16/09/2023 Ponteiros 50
Verificação em Linguagem C:
printf("\n Imprimindo o endereco na base hexadecimal \n");
printf("valor p_1 = %p, valor de *&p_1 = %p\n", p_1, *&p_1);

16/09/2023 Ponteiros 51
Ponteiros para Ponteiros (ponteiro de
ponteiro)
• Ponteiro simples

• Ponteiro de ponteiro

16/09/2023 Ponteiros 52
Ponteiros para Ponteiros (ponteiro de
ponteiro)
Uma variável que é um ponteiro para um ponteiro deve ser declarada
como tal.
Isso é feito colocando-se um asterisco adicional na frente do seu
nome.
Por exemplo, esta declaração diz ao compilador que novo balanço é
um ponteiro para um ponteiro do tipo float:

float **novoBalanço;

16/09/2023 Ponteiros 53
Ponteiros para Ponteiros (ponteiro de ponteiro)
É importante entender que novo balanço não é um ponteiro para um número de
ponto flutuante, mas, antes, um ponteiro para um ponteiro float.

Para acessar o valor desejado apontado indiretamente por um ponteiro para um


ponteiro, o operador asterisco deve ser aplicado duas vezes, como mostrado no
pequeno exemplo a seguir:

#include<stdio.h>
main(){
int x,*p,**q;
x=10;
p=&x;
q=&p;
printf("%d",**q); /*imprime o valor de x*/
}
Aqui, p é declarado como um ponteiro para um inteiro e q como um ponteiro para
um ponteiro para um inteiro. A chamada a printf() imprimirá o número 10 na tela.

16/09/2023 Ponteiros 54
Ponteiros para Ponteiros (ponteiro de ponteiro)
#include <stdio.h>
int main()
{
int x,*p,**q;
x=10;
p=&x;
q=&p;
printf("\nValor de x = %d", x); // imprime o valor de x
printf("\nValor de p = %p", p);
printf("\nValor de q = %p", q);
printf("\nConteudo apontado por q [*q] = %p", *q);
printf("\nConteudo apontado por q e por p [**q] = %d", **q);
printf("\n**q = %d",**q); // imprime o valor de x
return 0;
}
16/09/2023 Ponteiros 55
referências

• Manzano, José Augusto N.G, De Oliveira, Jayr Figueiredo. Algoritmos


– Lógica para desenvolvimento de programação de computadores.
Editora: Érica. Ano 2010
• SANTOS, H. J., Curso de Linguagem C – UFMG. Ano 1997.
• http://www.facape.br/nicolas/p1/04_-_Vetores.pdf
• http://everson.com.br/files/Vetor%20e%20Matriz.pdf
• http://74.125.47.132/search?q=cache:yUgu5VG-
fS0J:joaosantanna.110mb.com/Algoritmos/Vetores.pdf+programa%C
3%A7%C3%A3o+portugol+vetores&cd=10&hl=pt-BR&ct=clnk&gl=br

• Slides elaborado pelo prof. William Malvezzi, CEUB

16/09/2023 Ponteiros 56

Você também pode gostar