11 ponteiros em c prof. kariston pereira adaptado de material gentilmente fornecido pelo prof. rui...
TRANSCRIPT
11
Ponteiros em C Prof. Kariston Pereira
Adaptado de Material gentilmente fornecido pelo Prof. Rui Tramontin (DCC/UDESC)
UDESC – Prof. Kariston Pereira 22
Introdução Operações sobre Ponteiros Exemplos Ponteiros e Funções Alocação Dinâmica em C
Índice
UDESC – Prof. Kariston Pereira 3
Introdução Um ponteiro é uma variável cujo conteúdo é um
endereço de memória. Normalmente, de outra variável. Nesse caso, diz-se que o ponteiro aponta para a
variável.
Devem ser associados e um tipo de dados, e são declarados com um “*” antes do seu identificador:
int *ponteiro;
UDESC – Prof. Kariston Pereira 4
Operações sobre Ponteiros Operadores para ponteiros:
& - retorna o endereço de uma variável. * - retorna o conteúdo apontado pelo ponteiro.
int *ip; int x;
ip = &x; *ip = 100;
100ipx
UDESC – Prof. Kariston Pereira 5
Exemplo
int x = 1, y = 2; int *ip;
ip = &x; y = *ip; *ip = 3;
1x 2y ip13
UDESC – Prof. Kariston Pereira 6
Contra-Exemplo Ponteiros devem sempre ser inicializados.
int *ip;
*ip = 10;
int *ip; int x;
ip = &x; *ip = 10;
Erro na execução!
Ponteiro não inicializado.
Ok!
UDESC – Prof. Kariston Pereira 7
Ponteiros e Funções Parâmetros de funções podem ser
de dois tipos: Por valor Por referência;
Ponteiros são usados na passagem por referência.
UDESC – Prof. Kariston Pereira 8
Ponteiros e Funções Exemplo:
Função para troca de valores entre duas variáveis:swap(a, b);
void swap(int x, int y){ int temp; temp = x; x = y; y = temp;}
Não funciona!
•Parâmetros são alocados na pilha;
•Desalocados no final da execução.
UDESC – Prof. Kariston Pereira 9
Ponteiros e Funções Exemplo:
Função para troca de valores entre duas variáveis:swap(&a, &b);
void swap(int *x, int *y){ int temp; temp = *x; *x = *y; *y = temp;}
Funciona!
•Referências são passadas como parâmetro.
•A modificação é feita diretamente em a e b.
UDESC – Prof. Kariston Pereira 10
Alocação Dinâmica em C
UDESC – Prof. Kariston Pereira 11
Alocação Dinâmica em C A memória alocada pelas funções de alocação
dinâmica é obtida do heap.
O heap é a região de memória livre que se encontra entre o programa (com a área de armazenamento permanente) e a pilha (stack).
A linguagem C possui duas funções básicas para gerência de memória:
malloc(num de bytes) - aloca memória. free(endereço) - libera memória
UDESC – Prof. Kariston Pereira 12
Função malloc() Protótipo:
void *malloc(número_de_bytes);
Devolve um ponteiro do tipo void (sem tipo) para o início (1º byte) da área de memória alocada.
Para isto deve ser utilizado sempre um typecasting. x = (int *) malloc( sizeof(int) );
número_de_bytes é a quantidade de bytes alocada.
UDESC – Prof. Kariston Pereira 13
Função free() Protótipo:
void free( void *p );
Devolve memória previamente alocada apontada por p.
A utilização de free() com um valor de ponteiro qualquer poder ter resultados catastróficos.
A gerência de buracos no heap é responsabilidade do sistema operacional.
UDESC – Prof. Kariston Pereira 14
Exemplo#include <stdlib.h>#include <stdio.h>
char *a;int *b;
main (){ a = (char *) malloc(512); // Aloca 512 bytes
b = (int *) malloc(50*sizeof(int));// Aloca espaço
// para 50 inteiros. free(a);} Sistema
Operacional
100111010...
ab
HeapPointerTopo da áreaalocável
StackPointerTopo da pilha
Variáveis estáticas
Código objeto
Constantes
512 bytes
50*int = 200 bytes
UDESC – Prof. Kariston Pereira 15
Aritmética de Ponteiros
UDESC – Prof. Kariston Pereira 16
Aritmética de Ponteiros A linguagem C permite que se faça operações
aritméticas sobre ponteiros.
Oferece uma liberdade que nenhuma outra linguagem de programação oferece (exceto assemblers).
Isto é muito útil, porém é também muito perigoso!
Operações válidas com ponteiros: adição, subtração e comparação.
São muito úteis com vetores.
UDESC – Prof. Kariston Pereira 17
Semântica da Aritmética de Ponteiros A aritmética de ponteiros leva em o tamanho
ocupado pelo tipo de dados apontado.
Sejam p um ponteiro para o tipo T, e i um valor inteiro.
p + i é equivalente a:endereço( p ) + i * sizeof( T )
p - i é equivalente a:endereço( p ) - i * sizeof( T )
UDESC – Prof. Kariston Pereira 18
Ponteiros e Vetores Vetores podem ser tratados como
ponteiros.
Aritmética de ponteiros é usada para localizar elementos dentro de um vetor.
Dado um vetor A: A[i] ≡ *( A + i )
UDESC – Prof. Kariston Pereira 19
Ponteiros e Vetores Exemplo: int arr[10];
O tipo int ocupa 4 bytes na memória. Assumindo que arr está no endereço 1000, temos:
UDESC – Prof. Kariston Pereira 20
Exemplos
UDESC – Prof. Kariston Pereira 21
Exemplo 1
int *aponta;int valor1, valor2;
valor1 = 5;
aponta = &valor1;
valor2 = *aponta;
printf("%i\n", valor2);
UDESC – Prof. Kariston Pereira 22
Exemplo 2:invertendo um vetor
int x[5] = {1, 2, 3, 4, 5};
int *left = x;int *right = x + 4;
while(left < right){ int temp = *left; *left = *right; *right = temp; left++; right--;}
UDESC – Prof. Kariston Pereira 23
Exemplo 2int *p1, *p2, *p3, *p4, x=0;
p1 = &x;p2 = p1 + 1;p3 = p2 + 4;p4 = p3 - 5;
printf("%i\n", *p1); printf("%i\n", *p2); printf("%i\n", *p3); printf("%i\n", *p4);
printf("%i\n", p1); printf("%i\n", p2); printf("%i\n", p3); printf("%i\n", p4);
UDESC – Prof. Kariston Pereira 24
Exemplo 2int *p1, *p2, *p3, *p4, x=0;
p1 = &x;p2 = p1 + 1;p3 = p2 + 4;p4 = p3 - 5;
printf("%i\n", *p1); // 0 printf("%i\n", *p2); // “lixo”printf("%i\n", *p3); // “lixo”printf("%i\n", *p4); // 0
printf("%i\n", p1); // 1000printf("%i\n", p2); // 1004printf("%i\n", p3); // 1020printf("%i\n", p4); // 1000
UDESC – Prof. Kariston Pereira 25
char nome[30] = "João da Silva";char *p1, *p2;char car;int i;
p1 = nome;car = nome[3];car = p1[0];p2 = &nome[5];printf("%s", p2);p2 = p1;p2 = p1 + 5;printf("%s",(p1 + 5));printf("%s",(p1 + 20));
for (i=0; i < strlen(nome); i++){ printf ("%c", nome[i]);
p2 = p1 + i; printf ("%c", *p2);}
UDESC – Prof. Kariston Pereira 26
char nome[30] = "João da Silva";char *p1, *p2;char car;int i;
p1 = nome; // nome é ponteiro. Mesmo que p1 = &nome[0].car = nome[3]; // atribui 'o' a car.car = p1[0]; // atribui 'J' a car.p2 = &nome[5]; // p2 aponta para 6ª posição de nome ('d').printf("%s", p2); // imprime "da Silva".p2 = p1; // p2 aponta para o mesmo endereço de p1.p2 = p1 + 5; // equivalente a p2 = &nome[5].printf("%s",(p1 + 5)); // imprime "da Silva".printf("%s",(p1 + 20)); // imprime lixo! (cuidado).
for (i=0; i < strlen(nome); i++){ printf ("%c", nome[i]); // imprime 'J','o','ã',...
p2 = p1 + i; // p2 aponta para próximo caracter em nome. printf ("%c", *p2); // imprime 'J','o','ã',...}