Ponteiros em C
Prof. Kariston Pereira
Adaptado de Material gentilmente fornecido pelo
Prof. Rui Tramontin (DCC/UDESC)
1
Índice

Introdução

Operações sobre Ponteiros

Exemplos

Ponteiros e Funções

Alocação Dinâmica em C
UDESC – Prof. Kariston Pereira
2
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
3
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;
ip
x
UDESC – Prof. Kariston Pereira
100
4
Exemplo
int x = 1, y =
2;
int *ip;
x
1
3
y
2
1
ip
ip = &x;
y = *ip;
*ip = 3;
UDESC – Prof. Kariston Pereira
5
Contra-Exemplo

Ponteiros devem sempre ser inicializados.
int *ip;
Erro na execução!
*ip = 10;
Ponteiro não inicializado.
int *ip;
int x;
ip = &x;
*ip = 10;
Ok!
UDESC – Prof. Kariston Pereira
6
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
7
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;
}
UDESC – Prof. Kariston Pereira
Não funciona!
•Parâmetros são
alocados na pilha;
•Desalocados no final
da execução.
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;
}
Funciona!
•Referências são passadas
como parâmetro.
•A modificação é feita
diretamente em a e b.
UDESC – Prof. Kariston Pereira
9
Alocação Dinâmica em C
UDESC – Prof. Kariston Pereira
10
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
11
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
12
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
13
Exemplo
#include <stdlib.h>
#include <stdio.h>
char
int
*a;
*b;
main ()
{
a = (char *) malloc(512);
// Aloca 512 bytes
b = (int *)
malloc(50*sizeof(int));
// Aloca espaço
// para 50 inteiros.
StackPointer
Topo da pilha
HeapPointer
Topo da área
alocável
50*int = 200 bytes
512 bytes
Variáveis
estáticas
Código objeto
a
b
100111010...
Constantes
free(a);
Sistema
Operacional
}
UDESC – Prof. Kariston Pereira
14
Aritmética de Ponteiros
UDESC – Prof. Kariston Pereira
15
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
16
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
17
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
18
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
19
Exemplos
UDESC – Prof. Kariston Pereira
20
Exemplo 1
int *aponta;
int valor1, valor2;
valor1 = 5;
aponta = &valor1;
valor2 = *aponta;
printf("%i\n", valor2);
UDESC – Prof. Kariston Pereira
21
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
22
int
p1
p2
p3
p4
*p1, *p2,2
*p3, *p4, x=0;
Exemplo
=
=
=
=
&x;
p1 + 1;
p2 + 4;
p3 - 5;
printf("%i\n",
printf("%i\n",
printf("%i\n",
printf("%i\n",
*p1);
*p2);
*p3);
*p4);
printf("%i\n",
printf("%i\n",
printf("%i\n",
printf("%i\n",
p1);
p2);
p3);
p4);
UDESC – Prof. Kariston Pereira
23
int
p1
p2
p3
p4
*p1, *p2,2
*p3, *p4, x=0;
Exemplo
=
=
=
=
&x;
p1 + 1;
p2 + 4;
p3 - 5;
printf("%i\n",
printf("%i\n",
printf("%i\n",
printf("%i\n",
*p1);
*p2);
*p3);
*p4);
//
//
//
//
0
printf("%i\n",
printf("%i\n",
printf("%i\n",
printf("%i\n",
p1);
p2);
p3);
p4);
//
//
//
//
1000
1004
1020
1000
“lixo”
“lixo”
0
UDESC – Prof. Kariston Pereira
24
char
char
char
int
nome[30] = "João da Silva";
*p1, *p2;
car;
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
25
char
char
char
int
nome[30] = "João da Silva";
*p1, *p2;
car;
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','ã',...
}
UDESC – Prof. Kariston Pereira
26
Download

int *ponteiro