Вы находитесь на странице: 1из 44

Ponteiros

Introdução
• Variável que contém um endereço de
memória;
• Esse endereço é normalmente a posição de
uma outra variável na memória;
Sintaxe
• A forma para se declarar uma variável
ponteiro é:
– Tipo *variavel;
– int *cpf;
– char *nome;
Introdução
• Qualquer tipo de ponteiro pode apontar para
qualquer lugar na memória;
• Porém toda aritmética de ponteiro é feita
através do tipo base, portanto é importante
declarar o ponteiro corretamente.
Operadores de Ponteiros
• Operadores especiais: * e &
• & devolve o endereço da memória do seu
operando:
– Ex: end = &nome;
– Coloca em end o endereço da memória que
contém a variável nome.
– O endereço não tem relação com o valor de nome
Operadores de Ponteiros
• * é o complemento de &;
• Devolve o valor da variável localizada no
endereço que o segue;
• Ex: Se end contém o endereço da variável
nome,
– val=*end; coloca o valor de end em val.
– val recebe o valor que está no endereço end
Atribuição de Ponteiros
#include <stdio.h>

int main(int argc, char const *argv[]) {


int z=13;
int *ponteiro1, *ponteiro2;

ponteiro1=&z;
ponteiro2=ponteiro1;

printf("endereco de memoria que o ponteiro2 esta


apontando: %p\n", ponteiro2);
printf("endereco de memoria de z: %p\n", &z);
printf("valor de z: %d\n", *ponteiro2);
printf("endereco da variavel ponteiro2: %p\n", &ponteiro2);
return 0;
}
Aritmética de Ponteiros
• Adição – cada vez que o ponteiro é
incrementado, ele aponta para a posição de
memória do próximo elemento do seu tipo.
• Ex: p++;
Aritmética de Ponteiros
• Subtração – cada vez que o ponteiro é
decrementado, ele aponta para a posição de
memória do elemento anterior do seu tipo.
• Ex: p--;
Aritmética de Ponteiros
• Além de incremento e decremento, é possível
somar e subtrair inteiros de ponteiros;
– Ex: p1 = p1 +10; -> Faz p1 apontar para o décimo
elemento do tipo p1 adiante do elemento que ele
está atualmente apontado.
Tarefa1
• Crie uma função imprimeEndereco(int x) que
imprime o endereço da variável inteira x
passada para a função. Crie um programa e
nele crie uma variável inteira, imprima seu
endereço e então passe essa variável como
parâmetro para a função imprimeEndereco.
Compare a saída, esse comportamento é
esperado?
Tarefa 2
• Escreva uma função troca que receba dois
ponteiros do tipo inteiro e troque os valores
desses 2 inteiros.

– void troca(int *p1, int *p2);


Vetores e Ponteiros
• Quando se declara um vetor em C
– Int vetor[5]={1,2,3,4,5};
• O compilador calcula o tamanho em bytes
necessário para armazenar o vetor;
– (Tamanho1, tamanho2, tamanho3, tamanho4,
tamanho5) * 4 Bytes. Sizeof(int)
Vetores e Ponteiros
• double saldo[100];
• saldo é um ponteiro para &saldo[0] que é o
endereço para o primeiro elemento do vetor
saldo;
double *p1;
double saldo[100];
p1 = saldo;
Tarefa 1
• Escreva uma função receba um vetor vet com
5 inteiros. O método deve retornar o vetor vet
com o valor de cada posição muljplicado por
2. Os valores devem ser acessíveis fora do
método.
Tarefa 2
• Escreva um método que receba um vetor de
inteiros e retorne o maior elemento e o menor
elemento. (dica: usar passagem de parâmetro
por referência, já que os métodos só podem
retornar um único valor)
Organização da memória

High address

Lido de um
arquivo de
Low address programa pelo
exec
Segmento GVAR
Segmento BSS
Stack vs Heap
• Stack: Região da memória do computador que
armazena temporariamente variáveis criadas
por cada função (incluindo a função int
main()) e é gerenciada e otimizada pela CPU;
• Heap: Região da memória do computador que
não é gerenciada automaticamente. Para
alocar memória no heap é preciso utilizar as
funções malloc, calloc do C.
Stack vs Heap
Características Stack Heap
Acesso Rápido Relativamente lento
Alocação Automática Manual
Escopo Local Global
Tamanho Tamanho depende do S.O. Sem limites (depende da
qtde de memória física)
Redimensionamento Não Sim ( realloc() )
Eficiência Espaço é gerenciado pelo Espaço é gerenciado
S.O. e não se torna manualmente e pode ficar
fragmentado fragmentado
Stack vs Heap

• A principal vantagem de se armazenar na


stack para armazenar variáveis é que a
memória é gerenciada automaticamente para
você;
• Diferente da stack, variáveis criadas no heap
são acessíveis por qualquer função, em
qualquer lugar do programa.
Alocação dinâmica da memória
• Usar a função malloc para alocar uma
quantidade de memória;
• Usar essa porção de memória alocada
para a aplicação;
• Desalocar a memória (previamente
alocada) utilizando a função free.
Exemplo com Stack
Exemplo com Heap
Função malloc
• Alocação dinâmica de memória;
• Aloca um bloco de bytes consecutivos na
memória RAM do computador e devolve o
endereço desse bloco.
• O número de bytes é especificado no
argumento da função.
char *ponteiro;
ponteiro = malloc (1);
scanf ("%c", ptr);
Boa prática de programação
Sizeof
typedef struct {
int idImovel, diasAtraso;
double valor;
} ficha;

ficha *f;
f = malloc (sizeof (ficha));
f->idImovel= 1213;
f->diasAtraso= 5;
f.valor = 20343.05;
Função free
• Desaloca a porção de memória alocada por
malloc;
• A função free (ponteiro) avisa ao sistema que
o bloco de bytes apontado por ponteiro está
livre e disponível para reciclagem;
• A próxima chamada de malloc poderá tomar
posse desses bytes.
free (ponteiro);
ponteiro = NULL;
Função realloc
• Recebe o endereço de um bloco previamente
alocado com a função malloc (ou realloc) e o
número de bytes que o bloco redimensionado
deve ter.
• Aloca o novo bloco, transfere para ele o
conteúdo do bloco original, e devolve o
endereço do novo bloco.
Exemplo
int *vetor;
vetor = malloc (1000 * sizeof (int));
for (i = 0; i < 990; i++)
scanf ("%d", &vetor[i]);
vetor = realloc (vetor, 2000 * sizeof (int));
for (i = 990; i < 2000; i++)
scanf ("%d", &vetor[i]);
Vazamento de memória
• Ocorre quando um endereço de memória
alocado nunca é usado novamente e não é
liberado com a função free.
• Pode ocorrer quando:
– O endereço de memória é perdido;
– A função free nunca é chamada para liberar um
endereço alocado.
Vazamento de memória
Perdendo o endereço de memória
Perdendo o endereço de memória 2
Ponteiro pendente
(dangling pointer)
• Se um ponteiro apontar para um espaço da
memória que já foi liberada com a função
free, este se torna um ponteiro pendente.
– Comportamento imprevisível se a memória for
acessada;
– Falha de segmentação quando a memória não é
mais acessível;
– Riscos de segurança.
Ponteiro pendente - Exemplo
Ponteiro pendente - Exemplo
Ponteiro pendente - Exemplo
Lidando com ponteiros pendentes
• Atribuindo NULL ao ponteiro depois de
chamar a função free;
• Escrever funções especiais para substituir a
função free;
• Usar ferramentas de terceiros para detectar
ponteiros pendentes, ex: http://dmalloc.com
Tarefa3
• Escreva uma função chamada alocaMemoria
para alocar memória para um ponteiro. A
função recebe como parâmetro um ponteiro
do tipo inteiro, aloca um espaço na memória e
associa com esse ponteiro. Programa
principal: crie um ponteiro do tipo inteiro,
chame a função alocaMemoria e passe esse
ponteiro como parâmetro. Tente associar um
valor inteiro na memória que o ponteiro está
apontando depois da chamada da função
alocaMemoria.
Ponteiro para um ponteiro
• Um ponteiro que aponta para outro ponteiro
que aponta para um espaço de memória
– int **p1;
– double **p2;
Exemplo
Referências
• https://stackoverflow.com/questions/79923/what-
and-where-are-the-stack-and-heap
• https://www.learncpp.com/cpp-tutorial/79-the-
stack-and-the-heap/
• https://www.gribblelab.org/CBootCamp/7_Memory
_Stack_vs_Heap.html
• https://www.hackerearth.com/pt-
br/practice/notes/memory-layout-of-c-program/
• http://jonnypolotto.tk/wede/do-all-coupons-have-
the-same-barcode-3914.php

Вам также может понравиться