Ponteiros em C - joinville.udesc.br · Aritmética de ponteiros é usada para localizar elementos...
Transcript of Ponteiros em C - joinville.udesc.br · Aritmética de ponteiros é usada para localizar elementos...
UDESC - Rui J. Tramontin Jr. 1 1
Ponteiros em C
Prof. Rui Jorge Tramontin Jr.
UDESC - Rui J. Tramontin Jr. 2 2
Introdução
Operações sobre Ponteiros
Exemplos
Ponteiros e Funções
Alocação Dinâmica em C
Índice
UDESC - Rui J. Tramontin Jr. 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 - Rui J. Tramontin Jr. 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;
100
ip
x
UDESC - Rui J. Tramontin Jr. 5
Exemplo
int x = 1, y =
2;
int *ip;
ip = &x;
y = *ip;
*ip = 3;
1 x 2 y ip 1 3
UDESC - Rui J. Tramontin Jr. 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 - Rui J. Tramontin Jr. 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 - Rui J. Tramontin Jr. 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 - Rui J. Tramontin Jr. 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 - Rui J. Tramontin Jr. 10
Alocação Dinâmica em C
UDESC - Rui J. Tramontin Jr. 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 - Rui J. Tramontin Jr. 12
Função malloc()
Protótipo:
void *malloc(size_t n_bytes);
Devolve um ponteiro do tipo void (sem tipo) para o início (1º byte) da área de memória alocada.
Exemplo: int *x = malloc( sizeof(int) );
n_bytes é a quantidade de bytes alocada.
size_t é um tipo long int sem sinal.
UDESC - Rui J. Tramontin Jr. 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 - Rui J. Tramontin Jr. 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...
a
b
HeapPointer
Topo da área
alocável
StackPointer
Topo da pilha
Variáveis
estáticas
Código objeto
Constantes
512 bytes
50*int = 200 bytes
UDESC - Rui J. Tramontin Jr. 15
Aritmética de Ponteiros
UDESC - Rui J. Tramontin Jr. 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 - Rui J. Tramontin Jr. 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 - Rui J. Tramontin Jr. 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 - Rui J. Tramontin Jr. 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 - Rui J. Tramontin Jr. 20
Exemplos
UDESC - Rui J. Tramontin Jr. 21
Exemplo 1
int *aponta;
int valor1, valor2;
valor1 = 5;
aponta = &valor1;
valor2 = *aponta;
printf("%i\n", valor2);
UDESC - Rui J. Tramontin Jr. 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 - Rui J. Tramontin Jr. 23
Exemplo 2 int *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 - Rui J. Tramontin Jr. 24
Exemplo 2 int *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); // 1000
printf("%i\n", p2); // 1004
printf("%i\n", p3); // 1020
printf("%i\n", p4); // 1000
UDESC - Rui J. Tramontin Jr. 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 - Rui J. Tramontin Jr. 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','ã',...
}