Ponteiros são um dos recursos mais poderosos da linguagem C e de outras. Qualquer programa de utilidade prática escrito em C dificilmente dispensará o uso de ponteiros. A tentativa de evitá-los implicará quase sempre códigos maiores e de execução mais lenta.
Para quem está começando, pode parecer (e algumas vezes é) um tanto difícil. Mas não há outro caminho senão enfrentar a realidade.
São muitas as aplicações de ponteiros. A seguir, relação das mais comuns.
• Acessar endereços de memória que o programa aloca em tempo de execução.
• Acessar variáveis que não são visíveis em uma função.
• Manipulação de
arrays.
• Manipulação de
strings.
• Passar o endereço de uma função para outra.
• Retornar mais de um valor para uma função.
Ponteiro é uma variável que contém o
endereço de um objeto de dados, em geral uma outra variável. Essa é a razão para o seu nome: ele
aponta para outra variável.
Conforme qualquer variável em C, o ponteiro deve ser declarado antes de ser usado. Basta inserir o operador indireto (
*) após o tipo da variável
int *ptr;
Essa declaração define a variável
ptr como um ponteiro para uma variável do tipo
int (número inteiro).
A declaração de ponteiro não tem o mesmo significado da declaração de uma variável. Ela indica apenas o tipo de objeto de dados apontado e, desde que contém endereço de memória, o tamanho em bytes que ocupa não tem relação com o tamanho do objeto apontado. O tamanho do ponteiro é fixo e depende apenas do modelo de memória do sistema (2 bytes ou 4 bytes, normalmente).
Para declarar mais de um ponteiro por linha, usa-se um operador indireto (
*) para cada
char *ch1, *ch2; (são ponteiros para o tipo
char).
Se um operador for omitido (exemplo:
char *ch1, ch2;), a variável correspondente não será ponteiro e, certamente, provocará erro de execução se usada como tal.
O ponteiro pode ser declarado para qualquer tipo legal de variável em C (
char,
int,
float,
double, etc), além de
void, que seria um genérico, podendo apontar para qualquer tipo de dado.
Inicializando um ponteiro |
Topo | Fim |
A simples declaração de um ponteiro não o faz útil. É necessária a indicação da variável para a qual ele aponta.
 |
| Fig 01 |
int var;
int *ptr;
var = 10;
ptr = &var;
Na seqüência acima, são declarados uma variável tipo
int (
var) e um ponteiro para o mesmo tipo (
ptr). A terceira linha atribui o valor 10 a
var e a última linha inicializa o ponteiro
ptr.
Observa-se o uso do operador de endereçamento (
&) para inicialização do ponteiro. Isso significa, no código
ptr = &var;, que
ptr passa a conter o
endereço de
var, não o seu valor.
Supondo que o sistema é endereçado por 2 bytes, a Figura 01 acima dá uma idéia gráfica dessa associação: o conteúdo de
ptr é 4052, que é o endereço do primeiro byte da variável
var (
ptr ocupa 2 bytes por causa do endereçamento do sistema e
var também ocupa 2 bytes, mas por ser do tipo
int).
O valor 4052 para a posição de memória de
var é apenas ilustrativo. Na prática, dependerá do local de memória onde o programa foi carregado.
Com
ptr apontando para
var, é possível realizar operações com esta última de forma indireta, a partir de
ptr. Exemplos a seguir.
Acrescentando a linha
int newVar = *ptr;
ao código anterior, o valor de
newVar é 10, que é o valor de
var lido indiretamente através de
ptr.
E a linha
*ptr = 20;
modifica o valor de
var para 20, ou seja, altera de forma indireta através de
ptr.
É importante lembrar que um ponteiro declarado e não inicializado poderá ter conteúdo nulo ou aleatório, a depender da alocação sistema. Nessa condição, se o conteúdo apontado for modificado, algumas posições de memória terão seus valores indevidamente alterados e as conseqüências serão imprevisíveis.