You are on page 1of 36

Ponteiros

Ponteiros
Suponhamos que existem 2 amigos que
trocam informao entre eles.
Nome
Maria

Fone
Endereo
3424-2345 Rua 01, n 83

Carlos

3234-3222 Av. das Graas, n 05

Ponteiros
O conjunto dos amigos podem ser
representados graficamente por:

Maria

34242345
Rua 01, n 83

Carlos

32343222
Rua das
Graas, n 05

Ponteiros
Note que se falarmos de qualquer nome,
est se referindo ao contedo da
respectiva casa (nmero do fone).
Se estivessemos programando em C
printf(%d,Maria)
3424-2345
printf(%d,Carlos)
3234-3222

Ponteiros
O endereo da Maria Rua 01, n 83
O endereo do Carlos Rua das Graas,
n 05
Em C existe o operador &, que permite
saber qual o endereo de uma varivel,
ou seja, retorna o endereo de uma
varivel.

Ponteiros
Dessa forma para escrevermos os
endereos de Maria e Carlos:
printf(%d,&Maria)
printf(%d,&Carlos)

Rua 01, n 83
Av. das Graas, n 05

Ponteiros
Suponhamos que aparea o vizinho
LUCAS, que no possui telefone e Maria
autorizou a usar de sua casa.
LUCAS Rua 01,
Maria

34242345
Rua 01, n 83

n 83
Av. 7 de
Setembro, n 15

Ponteiros
Como pode se observar, a casa de
LUCAS um pouco diferente das
outras.
As outras podiam ser declaradas como:
Fone Maria, Carlos;

Ponteiros
A casa de LUCAS ter que ser
declarada como uma casa que contm
o endereo de outra casa. Isto ,
LUCAS aponta para uma casa com
fone.
Fone *LUCAS; /* LUCAS no tem um fone, e sim o
endereo em que se encontra um fone.*/

Ponteiros
Se LUCAS contm o endereo de
Maria porque foi iniciada do seguinte
modo:
LUCAS = &Maria;

Ponteiros
Repare nos seguintes valores:
Expresso
Maria
&Maria

Valor
3424-2345
Rua 01, n 83

LUCAS

Rua 01, n 83

&LUCAS

Av. 7 de Setembro, n 15

*LUCAS

3424-2345

Ponteiros
*LUCAS representa o valor que est
colocado no endereo armazenado em
LUCAS.
Note que falar de LUCAS o mesmo
que falar de &Maria, pois a varivel
LUCAS contm o valor do endereo de
Maria.
O endereo de LUCAS o local onde
fica a sua casa.

Ponteiros - conceito
Ponteiro so mecanismos de
manipulao de dados que permitem
manipular diretamente dados contidos
em endereos especficos de memria.

Carga Inicial Automtica de


Ponteiros
A carga inicial de ponteiros se faz
atravs do operador Endereo de: &

Carga Inicial Automtica de


Ponteiros
Exemplos:
int x = 5;
float pi = 3.14;
int * ptr_x = &x;

Carga Inicial Automtica de


Ponteiros
Um bom hbito para evitar problemas de
programao sempre a carga inicial
dos ponteiros
Existem situaes em que declaramos
um ponteiro e no queremos que ele
aponte para varivel alguma. Nesse
caso, ele deve apontar para NULL.

Carga Inicial Automtica de


Ponteiros
Exemplo:
int a = 5, b = 7;
int *ptr = NULL; /*ptr no aponta para
nada*/
ptr

NULL

1000

1001

1002

3000

3001

3002

Para colocar ptr apontando para a faz-se.


ptr = &a;

Carga Inicial Automtica de


Ponteiros
ptr

NULL

1000

1001

1002

3000

3001

3002

Aps a instruo anterior tem-se:


a =5
ptr = 1002 //Endereo de a
*ptr = 5
// Aquilo que est no endereo 1002
ou o contedo existente no endereo
apontado por PTR

Carga Inicial Automtica de


Ponteiros
Dessa forma, fazer
printf (%d, a);
equivalente a
printf (%d,*ptr);
Pois ptr aponta para a e *ptr corresponde ao valor de a.
ptr

NULL

1000

1001

1002

*ptr

3000

3001

3002

Carga Inicial Automtica de


Ponteiros
3. E se executssemos a instruo:
*ptr = 20; //coloca 20 no apontado por ptr
Qual seria ento a sada de?
printf (%d %d %d, a, b, *ptr);
5 20 20
Observe que ao colocar 20 no apontado por ptr est
mexendo diretamente na varivel b, pois endereo dela que
est contido em ptr.
ptr

NULL

1000

1001

1002

3000

3001

3002

*ptr

Exemplos (Ponteiro)
main()
cont igual a 100;
{
pont igual ao
int *pont, cont, val;
endereo de cont;
val igual ao
cont = 100;
contedo apontado
pont = &cont;
por pont que
val = *pont;
igual ao contedo de
printf(%d,val);
cont, ou seja, 100.
}

Exemplos (Ponteiro)
main( )
{
int x,y,*px,*py;
x = 100;
px = &x;
py = px;
y = *py;
printf(x = %d e y =
%d,x,y);
}

px tem o endereo
de x
py tem o endereo
de x
y vale 100, pois
recebe o contedo
de x, atravs do
ponteiro py.

EXERCCIOS
Seiejso variveis inteiras epeqponteiros paraint,
quais das seguintes expresses de atribuio so ilegais?
a)p = &i;b)*q = &j;c)p = &*&i;
d)i = (*&)j;
e)i = *&j;f)i = *&*&j;
g)q = *p;h)i = (*p)++ + *q

Vetores como ponteiros


Como o C trata vetores?
Quando voc declara uma matriz da seguinte
forma:
tipo_da_varivel nome_da_varivel [tam1][tam2] ...
[tamN];

O compilador C calcula o tamanho, em bytes,


necessrio para armazenar esta matriz.
Este tamanho :
tam1 x tam2 x tam3 x ... x tamN x tamanho_do_tipo

Vetores como ponteiros


O compilador ento aloca este nmero de bytes em
um espao livre de memria.
O nome da varivel que voc declarou na verdade
um ponteiro para o tipo da varivel da matriz.
Este conceito fundamental!
Eis porque: Tendo alocado na memria o espao
para a matriz, ele toma o nome da varivel (que
um ponteiro) e aponta para o primeiro elemento da
matriz.

Vetores como ponteiros


Mas a surge a pergunta: ento como que
podemos usar a seguinte notao?
nome_da_varivel[ndice]
Isto pode ser facilmente explicado desde que voc
entenda que a notao acima absolutamente
equivalente a se fazer:
*(nome_da_varivel+ndice)

Vetores como ponteiros


Porque que, no C, a indexao comea com zero?
Porque, ao pegarmos o valor do primeiro
elemento de um vetor, queremos, de fato,
*nome_da_varivel e ento devemos
ter um ndice igual a zero.
Sabe-se que:
*nome_da_varivel equivalente a nome_da_varivel[0]

Vetores como ponteiros


Apesar de, na maioria dos casos, no fazer muito
sentido, poderamos ter ndices negativos.
Estaramos pegando posies de memria
antes do vetor. Isto explica tambm porque o C no
verifica a validade dos ndices.
Ele no sabe o tamanho do vetor. Ele apenas aloca
a memria, ajusta o ponteiro do nome do vetor para
o incio do mesmo e, quando voc usa os ndices,
encontra os elementos requisitados.

Vetores como ponteiros


Vamos ver agora um dos usos mais importantes dos
ponteiros: a varredura sequencial de uma matriz.
Quando temos que varrer todos os elementos de
uma matriz de uma forma sequencial, podemos usar
um ponteiro, o qual vamos incrementando.
Qual a vantagem?
Considere o seguinte programa para zerar uma
matriz:

Vetores como ponteiros


int main ()
{
float matrix [50][50];
int i,j;
for (i=0;i<50;i++)
for (j=0;j<50;j++)
matrix[i][j]=0.0;
return(0);
}

Vetores como ponteiros


Podemos reescrev-lo usando ponteiros:
int main ()
{ float matrix [50][50];
float *p;
int count;
p=matrix[0];
for (count=0;count<2500;count++)
{
*p=0.0;
p++; }
return(0);}

Vetores como ponteiros


No primeiro programa, cada vez que se faz
matrix[i][j] o programa tem que calcular o
deslocamento para dar ao ponteiro. Ou seja, o
programa tem que calcular 2500 deslocamentos.
No segundo programa o nico clculo que deve
ser feito o de um incremento de ponteiro.
Fazer 2500 incrementos em um ponteiro
muito mais rpido que calcular 2500 deslocamentos
completos.

Vetores como ponteiros


H uma diferena entre o nome de um vetor e
um ponteiro que deve ser frisada: um ponteiro
uma varivel, mas o nome de um vetor no
uma varivel. Isto significa, que no se
consegue alterar o endereo que apontado
pelo "nome do vetor". Ou seja:

Vetores como ponteiros


int vetor[10];
int *ponteiro;
/* as operacoes a seguir sao invalidas */
vetor = vetor + 2; /* ERRADO: vetor nao eh variavel */
vetor++; /* ERRADO: vetor nao eh variavel */
vetor = ponteiro; /* ERRADO: vetor nao eh variavel */
/* as operacoes abaixo sao validas */
ponteiro = vetor; /* CERTO: ponteiro eh variavel */
ponteiro = vetor+2; /* CERTO: ponteiro eh variavel */

Vetores como ponteiros


O nome de um vetor um ponteiro constante.
Pode-se indexar o nome de um vetor.
Como consequncia podemos tambm indexar um
ponteiro qualquer.

Vetores como ponteiros


Exemplo:
#include <stdio.h>
int main ()
{
int matrix [10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int *p;
p=matrix;
printf ("O terceiro elemento do vetor e: %d",p[2]);
return(0);
}
Podemos ver que p[2] equivale a *(p+2).