Sie sind auf Seite 1von 33

Ponteiros na Linguagem C

Prof. lder Bernardi


Programao Estruturada e Estrutura de Dados
Vdeo-aulas
https://www.youtube.com/playlist?list=PLWZB9ryZXz1
MyU0KPf6V81ULGUyRXjs4i
Motivao
Toda varivel est em memria
Corresponde a um trecho da memria que pode ser
acessado pelo programa
Toda memria est organizada em endereos
Logo, uma varivel possui um endereo de memria
que marca onde o armazenamento dessa varivel inicia
H situaes onde necessrio manipular uma varivel
indiretamente
Acessando seu endereo de memria atravs de uma outra
varivel
(calma, veremos isso daqui a pouco )

3 13/9/2011 19:48
Perguntas
Como fao para passar uma varivel para uma funo e,
ao final da funo, o valor DA VARIVEL ser alterado?
Ex.: Escreva uma funo de soma simples que receba como
parmetro a varivel local resultado, operador1 e operador2
Ao fim da funo a varivel resultado DEVE ter o valor

4 13/9/2011 19:48
Ex 1 Soma sem ponteiros
void soma(int resultado, int op1, int op2)
{
resultado = op1+op2;
}

/*Se deseja que a soma altere a varivel resultado . Vai Funcionar????*/


int main()
{
int resultado = 0;
int op1 = 2;
int op2 = 2;

soma(resultado, op1, op2); //observe que soma no tem retorno

cout << resultado;


//Que valor vai ser apresentado?
}

5 13/9/2011 19:48
Seus Problemas Acabaram!

PONTEIROS!

6 13/9/2011 19:48
O que so ponteiros? *
Normalmente, toda varivel C declarada para armazenar
um valor numrico (bytes):
int servem para armazenar valores inteiros
float para armazenar valores numricos com preciso simples,e
assim por diante
Esses tipos fazem referncia a um determinado valor
Int a um num inteiro, float a um num fracionado, etc.
Existe um tipo particular de varivel em C que, ao invs de
conter valores numricos, armazena endereos de memria:
So os ponteiros (ou apontadores).
Um ponteiro uma varivel declarada para armazenar o endereo
de memria onde est armazenada outra varivel.
Declarando ponteiros
Como ponteiros so variveis, logo preciso declar-los para poder utiz-los
Exemplo de declarao:
int *p;
float *pParaFloat;

Declaraes de ponteiros so precedidas do smbolo * (asterisco)


Como no exemplo acima, onde declarada uma varivel ponteiro p, que
pode conter qualquer endereo de memria onde est armazenado um valor
inteiro
(L-se: "p um ponteiro para int).

Os ponteiros em C so tipados, isto , devem ter um tipo declarado e somente


podem apontar para variveis do mesmo tipo, com exceo dos ponteiros para
void, que podem apontar para variveis de qualquer tipo, mas tem utilizao
limitada.

8 13/9/2011 19:48
Operadores especficos para
Ponteiros

O operador &, quando colocado em frente ao nome de uma


varivel, obtm o endereo desta varivel.
Ao atribuir este endereo para um ponteiro, diz-se que o ponteiro
est "apontando para" a varivel.

O operador * somente pode ser utilizado com ponteiros (


*nomeDoPonteiro ). Ele obtm o valor da varivel apontada pelo
ponteiro. Esta operao chamada de "referncia indireta" .

9 13/9/2011 19:48
Inicializando Ponteiros
Nenhum ponteiro pode ser usado antes de ser inicializado
Enquanto no apontarem para um endereo vlido, tem-se o risco de o
programa ser abortado pelo sistema operacional por ter causado uma
operao ilegal (acesso endereo invlido de memria).
A popular falha de segmentao ou segmentation fault.
Logo, preciso inicializar todo ponteiro antes de podermos utiliz-los. Mas
como?

Pergunta-se:
Se um ponteiro deve referenciar (apontar, conter) o endereo de memria de
uma varivel como inicializo um ponteiro int *p com o endereo de int i?
Ex:
main(){
int *p, i;
p = ??;
}

10 13/9/2011 19:48
Inicializando Ponteiros
A maneira mais simples de inicializar um ponteiro
faz-lo apontar para uma varivel existente.
Ex.:
main(){
int *p, i;
p = &i;
}
Observe que se atribui o ENDEREO de i para p. NO o
valor! Pois p um PONTEIRO
Agora p contm o endereo de i;
Logo p aponta para o endereo de i

11 13/9/2011 19:48
Lendo o valor de uma varivel
apontada por um ponteiro
Para ter acesso ao valor (contedo) de uma varivel a qual um ponteiro aponta,
usa a sintaxe
*nomeDoPonteiro
L-se valor apontado por ponteiro
No exemplo
main(){
int *p, i =1;
p = &i;
}
Se se quiser ler o valor de i de maneira indireta atravs do ponteiro p, faz-se:
*p;
Ex.:
main(){
int *p, i=1;
p = &i;
cout << Contedo (valor) do endereo apontado por p << *p;
}

12 13/9/2011 19:48
Testando Referncia Indireta
int main(void)
{
int v=25, *p;
p = &v; /* p aponta para v */
cout << v: << v << p: << *p;
*p = 50; /* atribuio por referencia indireta */
cout << v: << v << p: << *p;

}
Sada: ??
Implemente e descubra por que?

13 13/9/2011 19:48
Aplicaes de Ponteiros

14 13/9/2011 19:48
Passagem de parmetros por
referncia em funes
Voltemos ao problema do Slide 3
Perguntas
Como fao para passar uma varivel para uma funo e,
ao final da funo, o valor DA VARIVEL ser alterado?
Ex.: Escreva uma funo de soma simples que receba como
parmetro a varivel local resultado, operador1 e operador2
Ao fim da funo a varivel resultado DEVE ter o valor

MAS COMO???
Veja o arquivo Ex1

16 13/9/2011 19:48
Ex 1 Soma sem ponteiros
void soma(int resultado, int op1, int op2)
{
resultado = op1+op2;
}

/*Se deseja que a soma altere a varivel resultado . Vai Funcionar????*/


int main()
{
int resultado =120;
int op1=2;
int op2=2;

soma(resultado, op1, op2); //observe que soma no tem retorno

cout << resultado;


//Que valor vai ser apresentado?

17 13/9/2011 19:48
Agora, como resolver
o problema?

Programando

18 13/9/2011 19:48
Soluo
#include <cstdlib>
#include <iostream>
using namespace std;
void soma(int *presultado, int op1, int op2)
{
*presultado = op1+op2;
}

int main()
{
int resultado;
int op1=2;
int op2=2;
soma(&resultado, op1, op2);
cout << "Resultado: " << resultado << endl;
//Que valor vai ser apresentado?
}

19 13/9/2011 19:48
Recapitulando
O que na realidade se quer que se possa acessar a
varivel resultado indiretamente dentro do corpo da
funo soma
Ento, qual a varivel que preciso ter na funo para
poder referenciar o contedo de outra?
?
Onde preciso ter a referncia ?
?
Como e onde a declaro para tal fim?
?

20 13/9/2011 19:48
Recapitulando
O que na realidade se quer que se possa acessar a
varivel resultado indiretamente dentro do corpo da
funo soma
Ento, qual a varivel que preciso ter para poder
referenciar o contedo de outra?
Uma varivel ponteiro
Onde preciso ter a referncia?
Dentro da funo soma
Como declaro para tal fim?
Preciso ter dentro da funo soma uma referncia a
resultado

21 13/9/2011 19:48
Soluo
Declaro o ponteiro para referenciar a
#include <cstdlib> resultado
#include <iostream>
using namespace std;
void soma( int *presultado, int op1, int op2)
{
*presultado = op1+op2;
} Atribuo ao valor apontado por presultado (ou
seja, a var resultado),
int main()
{
int resultado;
int op1=2;
int op2=2;
soma(&resultado, op1, op2);
cout << "Resultado: " << resultado << endl;
//Que valor vai ser apresentado?
Aqui passo o ENDERECO de resultado para a
} varivel ponteiro *presultado que usar o
endereo para poder
referenciar a varivel.

22 13/9/2011 19:48
Concluindo
Tendo um parmetro ponteiro em uma funo, posso
passar um endereo de uma varivel ao chamar esta
funo
void funcao(float *p)

Assim, no corpo da funo, posso acessar indiretamente


o contedo do endereo passado por parmetro
void funcao(float *p){
*p = 10.2; //altera o contedo do endereo de memria apontado por
p
}

23 13/9/2011 19:48
Ponteiros para estruturas de
dados compostas

24 13/9/2011 19:48
Ponteiros para vetores
Uma varivel representa um espao em memria para armazenar um
determinado tipo de valor
Um vetor uma varivel que capaz de armazenar N vezes um determinado
tipo
Em se tratando de vetores, o nome do vetor representa o endereo de memria
onde se inicia o armazenamento do vetor
O ndice (entre []) representa o deslocamento que se faz a partir do incio do
vetor na memria.
Logo, o ndice [0] representa o incio daquele vetor a partir do endereo de
memria onde se inicia o armazenamento do vetor;
[1] a prxima posio na memria; e assim por diante
Portanto, em C, quando se refere a um vetor, sem especificar seu ndice
(somente com o nome da varivel), se est referenciando o ENDEREO DE
MEMRIA da 1 posio de um vetor

25 13/9/2011 19:48
Ponteiros para vetores
Assim, em C
&vetor[0] o mesmo que vetor
Assim, como inicializo um ponteiro para um vetor ?
Ex.:
int vetor[] = {0,1,2,4,6};
int *pVetor;
?

26 13/9/2011 19:48
Ponteiros para vetores
Assim, em C
&vetor[0] o mesmo que vetor
Assim, como inicializo um ponteiro para um vetor ?
Ex.:
int vetor[] = {0,1,2,4,6};
int *pVetor;
pVetor = &vetor[0];
OU
pVetor = vetor;

Por que no preciso que o ponteiro seja um vetor?

27 13/9/2011 19:48
Resposta
Pois apontando para o incio da memria do vetor,
posso percorr-lo at o seu final indicando o
DESLOCAMENTO (posio do vetor) que se quer
acessar
Ex.: no ponteiro pVetor, acessando-se pVetor[2], se estar
acessando a terceira posio do vetor.

No acesso ao valor contido na posio apontada, NO


SE USA O CARACTERE * precendendo a varivel.
Pois o uso do ndice j indica o contedo partindo de um
deslocamento

28 13/9/2011 19:48
Exemplo
int main(void)
{
char txt[100], *p;
int i;
cout << "Digite algo: ";
cin >> txt;
p=txt; /* p = &txt[0] */
cout << "Um caracter por linha:\n";
for(i=0; p[i]!='\0'; i++)
cout << p[i] << "\n"; /* p[i] corresponde a txt[i] */
getchar();
return(0);
}

29 13/9/2011 19:48
Ponteiros para matrizes
(vetor = arranjo de uma dimenso);

O que uma matriz?


certo dizer que um vetor de vetores?
Ento, se para apontar para um vetor preciso de um
ponteiro. Do que preciso para apontar para um vetor de
de vetores?
Ponteiro para ponteiros
int main()
{
int m[2][2] = { {0,1}, {2,3} };
int **p,i,j;

p = m; // p = m[0]; // p = (int**)m
for(i=0; i<2; i++ )
{
cout << "\n";
for(j=0; j<2; j++)
cout << "\t " << m[i][j];
}

getchar();
return 0;
}
RECADO IMPORTANTE
Se seu compilador no permitir fazer, por exemplo:
int *p, i=1;
p = &i;
Dando um erro como:
/home/elder/PED/TesteGDB/main.cpp|20|error: cannot convert int [2][2] to int* in assignment

preciso fazer um cast para tipo do ponteiro que se est querendo atribuir,
ficando assim:
TIPO *p; i=1;
p = (TIPO*) i;
Na prtica:
int *p, i=1;
p = (int*) &i;
Ponteiros para Registros(struct)
Quando se trata de ponteiros que apontam para variveis do tipo struct, deve-se
observar uma peculiaridade
Quando se deseja acessar um campo do registro atravs de um ponteiro,
deve-se substituir o delimitador . (ponto) pela seta (->) SEM PRECEDER O
PONTEIRO PELO *
Exemplo:
struct data
{
int dia; int mes; int ano;
};
struct data hoje={17, 7, 2002};
struct data *ptr;
ptr = &hoje;
cout << "Ano: " << ptr->ano;
Outra forma de se acessar:
(*ptr).ano;
(*ptr).dia;

Das könnte Ihnen auch gefallen