Sei sulla pagina 1di 9

Endereos e ponteiros

Os conceitos de endereo e ponteiro so fundamentais


em qualquer linguagem de programao, embora
fiquem ocultos em algumas linguagens. Em C, esses
conceitos so explcitos. Dominar o conceito de
ponteiro exige algum esforo e uma boa dose de
prtica.

Endereos
A memria RAM de qualquer computador uma
sequncia de bytes. Cada byte armazena um de 256
possveis valores. Os bytes so numerados
sequencialmente e o nmero de um byte o seu
endereo (= address).
Cada objeto na memria do computador ocupa um
certo nmero de bytes consecutivos. Um char ocupa
1 byte. Um int ocupa 4 bytes e um double ocupa
8 bytes em muitos computadores. O nmero exato de
bytes de um objeto dado pelo operador sizeof: a
expresso sizeof(int), por exemplo, d o nmero de
bytes de um int no seu computador.
Cada objeto na memria tem um endereo. Na maioria
dos computadores, o endereo de um objeto o
endereo do seu primeiro byte. Por exemplo, depois das
declaraes
charc;

inti;
struct{
intx,y;
}ponto;
intv[4];

os endereos das variveis poderiam ser os seguintes


c89421
i89422
ponto89426
v[0]89434
v[1]89438
v[2]89442

O endereo de um objeto (como uma varivel, por


exemplo) dado pelo operador &. Se i uma varivel
ento
&i

o seu endereo. (No confunda esse uso de & com o


operador lgico and, que se escreve && em C.) No
exemplo acima, &i vale 89422 e &v[3] vale 89446.
Um exemplo: O segundo argumento da funo de
biblioteca scanf o endereo da varivel onde deve ser
depositado o objeto lido do dispositivo padro de
entrada:
inti;
scanf("%d",&i);

Exerccios 1

1. TAMANHOS. Compile e execute o seguinte programa:


2. intmain(void){
3. typedefstruct{
4. intdia,mes,ano;
5. }data;
6. printf("sizeof(data)=%d\n",
7. sizeof(data));
8. }

Ponteiros
Um ponteiro (= apontador = pointer) um tipo especial
de varivel que armazena endereos. Um ponteiro
pode ter o valor especial
NULL

que no endereo de lugar algum. A constante NULL


est definida na interface stdlib.h e seu valor 0 na
maioria dos computadores.
Se um ponteiro p armazena o endereo de uma
varivel i, podemos dizer p aponta para i ou p o
endereo de i. (Em termos um pouco mais abstratos,
diz-se que p uma referncia varivel i.) Se um
ponteiro p tem valor diferente de NULL ento
*p

o valor do objeto apontado por p. (No confunda esse


uso de * com o operador de multiplicao!) Por
exemplo, se i uma varivel e p vale &i ento dizer *p
o mesmo que dizer i.

Figura esquerda: um ponteiro p, armazenado


no endereo 60001, contm o endereo de
um inteiro. Figura direita: representao
esquemtica da situao.

H vrios tipos de ponteiros: ponteiros para caracteres,


ponteiros para inteiros, ponteiros para ponteiros para
inteiros, ponteiros para registros etc. O computador
precisa saber de que tipo de ponteiro voc est falando.
Para declarar um ponteiro p para um inteiro, diga
int*p;

Para declarar um ponteiro p para um registro reg, diga


structreg*p;

Um ponteiro r para um ponteiro que apontar um


inteiro declarado assim:
int**r;

(Veja, por exemplo, a declarao de uma matriz de


nmeros inteiros.)

Exemplos. Suponha que a, b e c so variveis inteiras


e veja um jeito bobo de fazer c=a+b:
int*p;//pumponteiroparauminteiro
int*q;
p=&a;//ovalordepoendereodea
q=&b;//qapontaparab
c=*p+*q;

Outro exemplo bobo:


int*p;
int**r;//rumponteiroparaponteiropara
inteiro
p=&a;//papontaparaa
r=&p;//rapontaparape*rapontaparaa
c=**r+b;

Aplicao
Suponha que precisamos de uma funo que troque os
valores de duas variveis inteiras, digamos i e j.
claro que a funo
voidtroca(inti,intj){//errado!
inttemp;
temp=i;i=j;j=temp;
}

no produz o efeito desejado, pois recebe apenas os


valores das variveis e no as variveis propriamente
ditas. A funo recebe cpias das variveis e troca os
valores dessas cpias, enquanto as variveis originais
permanecem inalteradas. Para obter o efeito desejado,
preciso passar funo os endereos das variveis:
voidtroca(int*p,int*q)
{
inttemp;
temp=*p;*p=*q;*q=temp;

Para aplicar essa funo s variveis i e j basta dizer


troca(&i,&j);

ou talvez
int*p,*q;
p=&i;q=&j;
troca(p,q);

Exerccios 2
1. Verifique que a troca de valores de variveis discutida
acima poderia ser obtida por meio de uma macro do
pr-processador:
2. #definetroca(X,Y){intt=X;X=Y;Y=t;}
3. ...
4. troca(i,j);

5. Por que o cdigo abaixo est errado?


6. voidtroca(int*i,int*j){
7. int*temp;
8. *temp=*i;*i=*j;*j=*temp;
9. }

10.
Um ponteiro pode ser usado para dizer a uma
funo onde ela deve depositar o resultado de seus
clculos. Escreva uma funo hm que converta minutos
em horas-e-minutos. A funo recebe um inteiro mnts e
os endereos de duas variveis inteiras, digamos h e m,
e atribui valores a essas variveis de modo que m seja
menor que 60 e que 60*h+m seja igual a mnts.
Escreva tambm uma funo main que use a
funo hm.

11.
Escreva uma funo mm que receba um vetor
inteiro v[0..n1] e os endereos de duas variveis
inteiras, digamos min e max, e deposite nessas
variveis o valor de um elemento mnimo e o valor de
um elemento mximo do vetor. Escreva tambm uma
funo main que use a funo mm.

Vetores e endereos
Os elementos de qualquer vetor (= array) tm
endereos consecutivos na memria do computador.
(Na verdade, os endereos no so consecutivos, uma
vez que cada elemento do vetor pode ocupar vrios
bytes. Mas o compilador C acerta os detalhes internos
de modo a criar a iluso de que a diferena entre os
endereos de elementos consecutivos vale 1.) Por
exemplo, depois da declarao
int*v;
v=malloc(100*sizeof(int));

o ponteiro v aponta o primeiro elemento de um vetor de


100 elementos. O endereo do segundo elemento do
vetor v+1 e o endereo do terceiro elemento v+2. Se
i uma varivel do tipo int ento
v+i

o endereo do (i+1)-simo elemento do vetor. As


expresses v+i e &v[i] tm exatamente o mesmo
valor e portanto as atribuies
*(v+i)=87;
v[i]=87;

tm o mesmo efeito. Analogamente, qualquer dos dois


fragmentos de cdigo abaixo pode ser usado para
preencher o vetor v:

for(i=0;i<100;++i)scanf("%d",
&v[i]);
for(i=0;i<100;++i)scanf("%d",v+
i);

Todas essas consideraes tambm valem se o vetor for


alocado estaticamente pela declarao
intv[100];

mas nesse caso v uma espcie de ponteiro constante,


cujo valor no pode ser alterado.

Exerccios 3
1. Suponha que os elementos de um vetor v so do tipo
int e cada int ocupa 8 bytes no seu computador. Se o
endereo de v[0] 55000, qual o valor da expresso v
+3?
2. Suponha que v um vetor declarado assim:
3. intv[100];

Descreva, em portugus, a sequncia de operaes


que deve ser executada para calcular o valor da
expresso &v[k+9].
4. Suponha que v um vetor. Descreva a diferena
conceitual entre as expresses v[3] e v+3.
5. O que faz a seguinte funo?
6. voidimprime(char*v,intn){
7. char*c;
8. for(c=v;c<v+n;v++)
9. printf("%c",*c);
10. }

11.
O seguinte fragmento de cdigo pretende decidir
se abacate vem antes ou depois de uva no dicionrio.
O que h de errado?
12. char*a,*b;
13. a="abacate";
14. b="uva";
15. if(a<b)
16. printf("%svemantesde%s\n",a,b);
17. else
18. printf("%svemdepoisde%s\n",a,b);

Potrebbero piacerti anche