Ponteiros
Introdução e Alocação Dinâmica
Conceito
•  Um PONTEIRO ou APONTADOR é uma variável
usada para armazenar um endereço de memória.
•  Normalmente, o endereço armazenado em um
PONTEIRO é a posição de uma outra variável na
memória.
•  Se uma variável contém o endereço e uma outra,
então a primeira variável é dita apontar para a
segunda.
2
Conceito
3
Declaração
•  De maneira geral, uma variável ponteiro de nome
ID é declarada assim:
•  ESPECIFICADORES * ID = INICIALIZADOR;
•  onde, o = INICIALIZADOR é opcional (como em
toda declaração de variável).
4
Operadores de Ponteiros
•  Existem dois operadores especiais para ponteiros:
o * e o &.
5
Operador &
•  Um operador unário que devolve o endereço na
memória do seu operando.
int m;
int * p;
p = &m; /* p recebe o endereço onde se localiza a var. m */ ...
6
Operador *
•  É o complemento de &. Quer dizer, devolve a variável
localizada no endereço armazenado em um apontador.
p = &m;
m = 3;
printf("%p", p); /* imprime o endereço de m */
printf("%d", *p); /* imprime 3 que é o conteúdo de m */ ...
7
Ponteiros e Arranjos
•  Há uma estreita relação entre PONTEIROS e
ARRANJOS (vetores, matrizes e strings).
O nome de um ARRANJO (vetor, matriz ou string) é
sempre um PONTEIRO para o primeiro elemento do
ARRANJO.
char str[80], *pstr; pstr = str; /* pstr aponta para str[0] */ 8
Ponteiros e Arranjos
•  Assim, a décima posição de um ARRANJO (vetor,
matriz ou string) pode ser acessada de duas
maneiras:
pstr = str; /* pstr aponta para str[0] */ prin5("%c", str[9] ); /* imprime o 10o elemento de str */ prin5("%c",*(pstr + 9)); /* imprime o 10o elemento de str */ 9
Aritmética de Ponteiros
•  Existem apenas duas operações aritméticas que
podem ser usadas com ponteiros: adição e
subtração.
•  Cada vez que um ponteiro é incrementado, ele
aponta para a posição de memória do próximo
elementodo seu tipo base.
•  Cada vez que um ponteiro é decrementado, ele
aponta para a posição de memória do elemento
anterior.
10
Aplicações
•  O correto entendimento e uso de ponteiros é
crítico para uma programação bem-sucedida
em C. Há pelo menos três razões para isto:
•  ponteiros fornecem os meios pelos quais as
funções podem modificar seus argumentos
•  formam a base para a alocação dinâmica
(variáveis no heap)
•  aumenta a eficiência de certas rotinas
•  De agora em diante, até o final do curso,
iremos explorar em variados graus de
detalhes o conceito básico de ponteiros.
11
Atividades
•  Escreva um programa em C que preencha um
vetor de 10 números com os valores: 1,2... 10.
Depois imprima o valor na posição do vetor e o
endereço de memória que se encontra aquele
valor.
•  Escreva um programa em C que inicializa uma
string de caracteres e percorre essa string usando
aritmética de ponteiros.
12
Alocação Dinâmica
•  ALOCAÇÃO DINÂMICA é o processo através do
qual um programa pode criar novas variáveis
(áreas de memória) em tempo de execução.
•  Variáveis alocadas dinâmicamente são criadas em
uma área de memória livre chamada de HEAP e
são acessadas através de PONTEIROS.
13
Heap
14
Funções de Alocação Dinâmica –
ANSI - #include <stdlib.h>
•  void * calloc(size_t num, size_t size);
•  Aloca uma quantidade de memória igual a num*size.
Isto é, aloca memória suficiente para um ARRANJO
de num VARIÁVEIS de tamanho size.
•  Devolve o endereço para o primeiro byte da região
alocada. Se não houver memória suficiente para
satisfazer a solicitação, é devolvido NULL (endereço
nulo).
15
Funções de Alocação Dinâmica –
ANSI - #include <stdlib.h>
•  void * malloc(size_t size);
•  Aloca uma quantidade de memória igual a size. Isto
é, aloca memória suficiente para uma VARIÁVEL de
tamanho size.
•  Devolve o endereço para o primeiro byte da região
alocada. Se não houver memória suficiente para
satisfazer a solicitação, é devolvido NULL (endereço
nulo).
16
Funções de Alocação Dinâmica –
ANSI - #include <stdlib.h>
•  void * realloc(void * ptr, size_t size);
•  Modifica o tamanho da memória previamente
alocada apontada por ptr para um novo tamanho
especificado por size. O valor size pode ser maior ou
menor que o original.
•  Retorna o endereço para o primeiro byte da região
de memória redimensionada.
•  Se não houver memória suficiente no HEAP para
satisfazer a solicitação, é devolvido NULL (endereço
nulo) e o endereço originalmente em ptr é deixado
inalterado.
17
Funções de Alocação Dinâmica –
ANSI - #include <stdlib.h>
•  void free(void * ptr);
•  Devolve ao HEAP a memória apontada por ptr,
tornando a memória disponível para alocação futura.
•  Deve ser chamada somente com um PONTEIRO ptr
cujo endereço de memória foi previamente alocado
por meio de uma das funções do sistema de
alocação dinâmica (calloc(), malloc(), realloc()).
18
Outras - #include
<string.h>
•  char * strdup(const char * pstr);
•  Duplica a STRING apontada por pstr. Ou seja, aloca
no HEAP strlen(pstr)+1 bytes e copia a STRING
começando em pstr para o endereço alocado.
•  Retorna o endereço alocado contendo uma cópia da
STRING apontada por pstr ou NULL caso não haja
memória suficiente no HEAP.
19
Exemplo Outras
•  Ex.: O trecho de código abaixo:
char str[] = "Teste";
char * pstr = strdup(str);
•  É equivalente a:
char str[] = "Teste";
char * pstr = calloc(strlen(str) + 1, sizeof char);
strcpy(pstr,str);
20
Ponteiro para Funções
21
Ponteiro para Funções Exemplo
1. 
#include <stdio.h> 2. 
3. 
4. 
5. 
int compara(int a, int b) { if (b < a) return 1; return 0; } 6. 
7. 
int ordenacao (int *vet, int size, int (* compara)(int a, int b)) { int i, j, tmp, sel; 8. 
9. 
10. 
11. 
12. 
for (i=0; i<size-­‐1; i++) { sel = i; for (j=i+1; j<size; j++) if (compara(vet[sel], vet[j])) sel = j; 13. 
14. 
15. 
16. 
tmp = vet[i]; vet[i] = vet[sel]; vet[sel] = tmp; } 17. 
} 22
Ponteiro para Funções Exemplo
1.  int main() { 2.  int vet[7] = {5,6,1,2,3,7,4}; 3.  int i; 4.  ordenacao (vet, 7, compara); 5.  for (i=0; i<7; i++) prin5("%d ", vet[i]); 6.  return 0; 7.  } 23
Download

Ponteiros