Ponteiros oferecem um eficiente e prático meio de acesso e manipulação dos elementos de uma
array. Sejam, por exemplo, uma
array e um ponteiro declarados conforme linhas abaixo.
int ar[] = {10, 50, 20, 30};
int *ptr;
 |
| Fig 01 |
ptr = &ar[0];
A linha acima inicializa o ponteiro, associando-o ao primeiro elemento da
array. E a Figura 01 ao lado dá uma idéia gráfica da operação.
Obs: conforme já mencionado, o valor 4052 é meramente ilustrativo. Depende da localização de memória onde o programa é carregado.
Uma vez apontado para o primeiro elemento da
array, o valor deste último pode ser acessado ou modificado via ponteiro de forma idêntica à já vista para variáveis simples. As linhas abaixo, por exemplo, atribuem o valor de
ar[0] a
newVar (1ª linha) e o modificam para 15 (2ª linha).
int newVar = *ptr;
*ptr = 15;
É fácil concluir que os demais elementos da array podem ser acessados via incremento ou decremento do ponteiro, uma vez que ele contém endereço.
A
aritmética do ponteiro é estruturada de forma a facilitar essa operação. Considera-se, agora, que
ptr é incrementado conforme linha abaixo
ptr++;
Se fosse uma variável comum, o seu conteúdo seria simplesmente aumentado de uma unidade com o operador
++. No caso de ponteiro, o conteúdo é incrementado do número de bytes correspondente a uma variável do tipo para o qual ele aponta.
Neste exemplo, desde que
ptr é do tipo
int (que usa 2 bytes), o seu endereço real passa de 4052 a 4054, ou seja, aponta para o segundo elemento da
array. Assim, todos os seus elementos podem ser apontados via incremento ou decremento do ponteiro (
ptr++ ou
ptr--, por exemplo).
Se, em vez de
int, os dados e ponteiro fossem, por exemplo, tipo
float (4 bytes), cada incremento ou decremento unitário do ponteiro fariam seu valor mudar de 4 bytes, permitindo o correto acesso a cada elemento. Isso significa que o programador não precisa se preocupar com o real conteúdo do ponteiro. Basta considerar as correspondências unitárias, isto é, se o ponteiro é incrementado ou decrementado de um, ele aponta para o próximo elemento ou para o elemento anterior.
Cabe, entretato, ao programador manter o ponteiro dentro dos limites da
array. Se ultrapassar e o valor for modificado, resultados imprevisíveis podem ocorrer. Em geral, os compiladores não verificam isso.
A inicialização do ponteiro foi proporcionada pela linha já vista
ptr = &ar[0];
Mas também pode ser feita na forma
ptr = ar;
Isso significa que o nome (sem o índice dado pelos colchetes) de uma
array é, na realidade, um ponteiro e pode ser usado da mesma maneira.
Ponteiros para estruturas |
Topo | Fim |
Ponteiros para estruturas são escritos de forma similar aos anteriores. A principal diferença é o uso do operador
-> para acesso aos membros. Seja exemplo a seguir.
#include <stdio.h>
struct telelista{
char nome[15];
char ddd[2];
char num[10];
};
struct telelista *ptr;
main(){
struct telelista pedro = {
"Pedro da Silva", "99", "123-456"};
ptr = &pedro;
printf( "%s", ptr->nome );
}
No programa acima, após a declaração da estrutura, é definido um ponteiro dela (
ptr) de forma similar aos ponteiros de outros tipos.
A linha
ptr = &pedro; inicializa o ponteiro e, como argumento de
printf, é usado o operador de ponteiro para estrutura
ptr->nome
Essa declaração tem o mesmo efeito da sem ponteiro
pedro.nome.