Disciplina:
Estrutura de Dados
Tema da aula:
Ponteiro
Função: Passagem de argumentos por Valor
Função : Passagem de argumentos através de Ponteiros Alocação Estática de Memória
Alocação Dinâmica de Memória: malloc e free
Ponteiro
PLT: 706
Como funcionam os Ponteiros
• O
int
guardam inteiros.
• O
float
guardam números
de ponto flutuante.
23
45,89
de ponto flutuante.
• O
char
guardam caracteres.
•
O ponteiro guardam
endereços de memória
.
ABC
• Um Ponteiro é uma variável que contém o endereço de
Não entendi!
que contém o endereço de memória de outra variável.
• Podemos ter um ponteiro para qualquer tipo de
Como funcionam os Ponteiros
–
Quando você anota o endereço de um colega
você está criando um ponteiro
. O ponteiro é
este seu pedaço de papel. Ele tem anotado
um endereço. Qual é o sentido disto? Quando
um endereço. Qual é o sentido disto? Quando
você anota o endereço de um colega, depois
você vai usar este endereço para achá-lo. Da
mesma maneira, uma agenda, onde são
guardados endereços de vários amigos, poderia
ser vista como sendo uma
Declarando e Utilizando Ponteiros
• Para declarar um ponteiro temos a seguinte forma:
tipo_do_ponteiro *nome_da_variável;
• É o asterisco (*) que faz o compilador saber que
aquela variável não vai guardar um valor mas sim um endereço para aquele tipo especificado. Exemplos:
endereço para aquele tipo especificado. Exemplos:
int ct;
declara um inteiroint *pt1;
declara um ponteiro para um inteiroInicializando Ponteiros
•
O ponteiro deve ser inicializado, ou
seja, apontado para algum lugar
conhecido, antes de ser usado.
conhecido, antes de ser usado.
Inicializando Ponteiros
• Podemos então deixar que o compilador faça este trabalho por nós. Para saber o endereço de uma variável basta usar o operador &.
Veja o exemplo:
int contador=20; 20
int contador=20;
Criamos um inteiro “contador” com valor 20.
int *pt;
Declaramos o ponteiro inteiro “pt”
pt=&contador;
Temos agora o endereço da variável
Inicializando Ponteiros
• Como nós colocamos um endereço em pt, ele está agora "liberado" para ser usado.
Podemos, por exemplo, alterar o valor de
contador usando pt.
• Vamos usar o operador "inverso" do
• Vamos usar o operador "inverso" do
operador &. É o operador *. No exemplo, uma vez que fizemos pt=&contador a expressão
Inicializando Ponteiros
•
Observação importante
:
apesar do símbolo ser o mesmo, o
operador
* (multiplicação)
não é o
operador
* (multiplicação)
não é o
mesmo operador que o
• Para declararmos variáveis do tipo Ponteiro
int *px, *py;
Isso cria duas variáveis do tipo ponteiro (px e py). Essas variáveis podem conter
Por favor,
explica ai novamente...
(px e py). Essas variáveis podem conter
endereços de variáveis do tipo int.
• Operadores
& operador direto que retorna o endereço da variável operando
Exemplo de Ponteiros - 01
#include <stdio.h> int main ()
{ int num,valor;
int *pt;
num=55;
pt=# // Pega o endereco de num */
valor=*pt; // Valor e igual ao valor armazenado em num
printf ("Valor: %d\n",valor);
printf ("Endereco para onde o ponteiro aponta: %p\n",pt); printf ("Valor da variavel apontada: %d\n",*pt);
Exemplo de Ponteiros - 02
Muda o valor de uma variável de forma indireta
#include <stdio.h> int main ()
{ int numero,*pz; numero=55;
pz=№ // Pega o endereço de num
pz=№ // Pega o endereço de num
printf ("\nValor inicial: %d\n",numero);
// Muda o valor de numero de uma maneira indireta
*pz=100;
printf ("\nValor final: %d\n",numero); return(0);
Adição e Subtração com Ponteiros
•
Vamos imaginar que p é um ponteiro.
p++ ou p--
ele anda 8 bytes na
memória, ou seja, muda o valor do
memória, ou seja, muda o valor do
endereço de memória.
Qual o resultado de y?
4
0 0
2293476
y x
p
4
4 44
Por favor, faz uma
revisão sobre ponteiros!
int bb = 10; int cc = 0;
int *zz; declara um ponteiro do tipo inteiro de nome zz zz = &bb coloca o endereço de bb em zz
zz = &bb coloca o endereço de bb em zz
cc = *zz coloca o valor que esta no endereço zz em cc
10 0 229346
int cc
ponteiro zz
int bb
• Em C todos os parâmetros de funções são passados por valor
• Assim uma cópia dos valores dos argumentos é
Função
Passagem de argumentos
por Valor
• Assim uma cópia dos valores dos argumentos é dada à função que é chamada e ela cria outras variáveis temporárias para armazenar esses valores
• Em C uma função chamada não pode alterar o valor de uma variável da função que a
int main(){ int valorX; intvalorY; valorX = 5; valorY = 5;
printf("\nNo main...");
printf("\n\tO Valor de a: %d e o seu endereco e: %d\n", valorX, &valorX); printf("\tO Valor de b: %d e o seu endereco e: %d", valorY, &valorY);
somaDois(valorX,valorY); Isso a gente
somaDois(valorX,valorY);
printf("No main novamente...");
printf("\n\tO Valor de a: %d e o seu endereco e: %d\n", valorX, &valorX); printf("\tO Valor de b: %d e o seu endereco e: %d\n", valorY, &valorY); return(0); } Função: Passagem de argumentos através de Ponteiso
• Agora vamos passar como parâmetros da função os ponteiros de variáveis do
Função
Passagem de argumentos através de Ponteiros
função os ponteiros de variáveis do
main, desta forma conseguimos alterar o valor de uma variável do main dentro da função que foi chamada.
Hã???
int main(){ int valorW; valorW = 5;
printf("\nNo main...");
printf("\n\tO Valor de valorW: %d e o seu endereco e: %d\n", valorW, &valorW);
somaTres(&valorW);
printf("No main novamente...");
printf("\n\tO Valor de valorW: %d e o seu endereco e: %d\n", valorW, &valorW); return(0);
} Função: Passagem
Passei o endereço da variável
como parâmetro
Mostra outra ai...!
} Função: Passagem
de argumentos através de ponteiros
Recebe um ponteiro
int main(){
int valorA = 10; int valorB = 200;
troca(&valorA, &valorB); printf("Valor A = %d\n",valorA); printf("Valor B = %d\n",valorB); return(0); } Função Passagem de argumentos através de Ponteiros Passa o endereço
das variáveis como parâmetros
Na função os parâmetros são declarados como ponteiros: p1 e p2
}
O valor do ponteiro p1
O endereço do ponteiro &p1
O valor variável apontada pelo ponteiro *p1
int main(){
int valorQ; int valorE;
atualiza(&valorQ, &valorE); printf("Valor Q = %d\n",valorQ); printf("Valor E = %d\n",valorE); return(0); } Função Passagem de argumentos através de Ponteiros Passa o endereço
das variáveis como parâmetros
Na função os parâmetros são declarados como ponteiros: pQ e pE
}
No main eu criei as variáveis, mas não coloquei dados nas vari[aveis, a atualização das variáveis foram
realizadas pela função “atualiza”.
Para fazer que
pn
aponte para o mesmo lugar quepm
int hh=100; int *pm, *pn;
pm = &hh; // Pega o endereco de hh e coloca em pm
Atenção para alguns detalhes
muito importantes... 1
pm = &hh; // Pega o endereco de hh e coloca em pm
pn=pm; // Pega o endereco de pm e coloca em pn
Para fazer que o conteúdo apontado por pn tenha o mesmo conteúdo da variável apontada por pm
*pn=*pm; // Pega o valor apontador por pm e coloca pn
100 2293400 2293400
pn
bb pm
100 *pm
Os ponteiros devem
ser inicializados!!!
Outro detalhe muito
importante... 2
Se não inicializarmos um ponteiro pode fazer com que ele esteja
alocando um espaço de memória utilizado,
main (){
int x int *pt; x =13;
*pt =x; //posição de memória de pt é indefinida!
}
de memória utilizado, por exemplo, pelo
sistema operacional
Vai dar erro!
main (){
int x int *pt; x =13;
E como eu resolvo isso de inicializar ponteiro?
Inicializando o ponteiro
com algum endereço!
x =13;
pt = &x;
//inicializei pt com o endereço de x*pt =x; //posição de memória de pt é definida!
main (){
float salario = 2500; float novoSalario = 0; int *pt;
//inicialize pt com o //endereço de salario
pt = &salario;
Memória RAM
Identificação Endereço da
Memória Conteúdo
Windows 0100100 até
0300100
Sistema operacional Windows
Dev C++ 0300101 até Programa
pt = &salario;
} Dev C++ 0300101 até0400100 Programa Dec C++
salario 2293400 2500
novoSalario 2293412 0
pt 2293424 2293400
O ponteiro deve ser inicializado, antes de ser usado. int contador=20; Criamos um inteiro “contador”.
int *pt; Declaramos o ponteiro inteiro “pt”
pt=&contador; Endereço do “contador” armazenado em pt
Revisão
Ponteiros
pt=&contador; Endereço do “contador” armazenado em pt
*pt=12. Muda o valor do “contador” para 12.
Alocação
Estática e
Dinâmica de
Memória
PLT: 706
Alocação Estática de Memória
•
Alocação estática de memória ocorre
antes que o programa comece a ser
executado
,
por exemplo:
29
por exemplo:
Alocação Dinâmica de Memória
• Em determinados sistemas a quantidade de memória que deve ser alocada só se torna conhecida durante a execução do programa, assim é necessário recorrer ao processo de
alocação dinâmica de memória.
30
alocação dinâmica de memória.
• O processo de alocação retorna um endereço físico de memória para o tipo de variável que se pretende guardar. O endereço é guardado num apontador.
Alocação Dinâmica de Memória
• A alocação dinâmica é gerenciada pelas
funções
malloc e free, que estão na
biblioteca
stdlib
. Para usar esta
biblioteca, é preciso incluir no programa:
31
biblioteca, é preciso incluir no programa:
Função malloc
• malloc , abreviatura de memory allocation,
aloca um bloco de bytes consecutivos na memória do computador e devolve
o endereço desse bloco em um apontador, por exemplo: Tipo char ocupa 1 byte
32
por exemplo:
char *ponteiro;
ponteiro =
(char*)
malloc
(1);
Aloca 1 byte de memória e
coloca o endereço em um ponteiro
Função malloc
• O retorno de malloc é um ponteiro void*
então temos que converter o ponteiro void* no ponteiro do tipo correto que no exemplo abaixo é o char.
33
abaixo é o char.
char *ponteiro;
ponteiro = (char*)
malloc
(1);
Operador
sizeof
Em determinados casos podemos não saber a quantidade de bytes devemos alocar,
então utilizamos o operador
sizeof
.#include <stdio.h> #include <stdlib.h> int main (void) {
int iNumero = 0;
34
int iNumero = 0; char cLetra = 'A';
struct data {int dia,mes,ano;};
printf ("sizeof (int) = %d\n", sizeof(iNumero)); printf ("sizeof (char) = %d\n", sizeof(cLetra)); printf ("sizeof (data) = %d\n", sizeof(data)); return (0);
}
Função free
• As
variáveis alocadas estaticamente dentro de
uma função desaparecem quando a execução
da função termina
.
• As variáveis alocadas dinamicamente
• As variáveis alocadas dinamicamente
continuam a existir mesmo depois que a
execução da função termina.
Operador sizeof
#include <stdio.h> #include <stdlib.h>
struct data {int dia,mes,ano;};
int main()
{ data *p;
p =(data*) malloc (sizeof(data));
p.dia=10; p.mes=3; 36 utilizado no malloc p.mes=3; p.ano=2012; printf("Dia:%d\nMes:%d\nAno:%d\n", p.dia, p.mes, p.ano);
free(p);
Operador sizeof
#include <stdio.h> #include <stdlib.h> int main()
{ int *p;
p = (int*)malloc(sizeof(int));
if (p == null)
“Há memória suficiente disponível para alocar um bloco de memória do tamanho solicitado?“
37
utilizado no malloc
{ printf("ERRO: Sem memória\n"); return 1;
}
*p = 5;
printf("%d\n", *p);
free(p);
Referências
• Feofiloff, Paulo. Alocação dinâmica de memória; Disponível em:
<http://www.ime.usp.br/~pf/algoritmos/aulas/ aloca.html>. Acesso em: 14/04/2014.
MUITO OBRIGADO!
viniciussouzamg@gmail.com