Ponteiros, referência e dereferência [C,C++]

Ponteiros

Ponteiros são as mais poderosas e também as mais controversas ferramentas da linguagem C e C++.

Ponteiros foram abolidos de linguagens novas baseadas em C, como por exemplo Java. Mas, um programa que utiliza ponteiros sabiamente tem um desempenho muito maior, pois ponteiros trabalham diretamente com a memória. Dessa forma, praticamente, podemos manipular toda a quantia de memória do computador, mesmo que seja pouca ou muita.

Ponteiros como o próprio nome diz, é quem aponta. Sua única função, mas de extrema importância, é guardar o endereço de memória de uma variável.

Quando declaramos uma variável e executamos o programa, o sistema operacional se encarrega de alocar (reservar) o espaço necessário para o tipo de dado e “marca” aquele espaço de memória com um nome, que é o nome da variável. O papel do ponteiro é guardar exatamente este endereço.

Como ponteiros guardam endereços de memória, podemos guardar o endereço de qualquer parte da memória, mesmo que este espaço não tenha sido reservado no início da execução do programa.

Podemos declarar ponteiros ou usar referenciamento e dereferenciamento. Ponteiros são declarados como se fossem variáveis, mas contendo um indicador (que é um asterisco).

Por exemplo, se formos criar dois ponteiros, sendo um para um endereço de memória contendo um dado float e outro contendo um int, faríamos:

Pronto, agora já temos nossos ponteiros criados. Agora, vamos ver realmente como eles funcionam.

Referência

Referência é quando nos referimos diretamente ao identificador do endereço da memória.

A memória é na verdade uma grande tabela com células sequenciais, cada célula tem seu próprio endereço que segue um padrão contínuo. Ou seja, a primeira célula será 0x00000000, a segunda 0x00000001, a terceira 0x00000002, e assim por diante.

Quando fazemos referência, estamos obtendo exatamente este valor, que é o endereço da célula na memória.

A referência é dada pelo operador &.

Então, vamos imaginar que temos uma variável inteira chamada var1 que vale 100. Iremos criar um ponteiro chamado ptr1 que irá obter o endereço de memória onde está var1.

Perceba que aqui nós atribuímos a ptr1 o endereço de memória de var1 (&var1) e não o valor contido em var1.

Portanto, o valor de ptr1 não será 100, mas um endereço de memória 0x “algum hexadecimal”. Pois é impossível saber qual será o endereço de uma variável antes da execução do programa.

Dereferência

Dereferência é quando nos referimos ao valor contido no endereço armazenado, ou seja, é o contrário da operação de referência.

A dereferência busca o valor que está no endereço gravado no ponteiro, isso quer dizer que o valor obtido não está no ponteiro, mas no endereço que ele aponta. É importante entender isso porque quando alteramos o valor referenciado pelo ponteiro, na verdade estamos alterando o valor da variável original e não do ponteiro.

A dereferencia é dada pelo operador *.

Ainda usando o exemplo da variável var1.

Portanto, resumidamente, ponteiros se utilizam de referência e dereferência para acessar a memória, sendo a referência (&) o endereço de memória e a dereferência (*) o valor contido no endereço de memória.

Erros Comuns ao Utilizar Ponteiros

Um dos problemas que levaram a extinção do uso de ponteiros em linguagens mais recentes baseadas em C são os erros de lógica cometidos por programadores (inclusive experientes) que muitas vezes levava o programa ao crash ou erro fatal. A seguir, estão alguns problemas comuns que lidamos ao trabalharmos com ponteiros.

Ponteiros devem sempre apontar para algum endereço de memória. Portanto, todo ponteiro deve ser inicializado antes de ser utilizado.

Ex.int *ptr1; cout << ptr1;.

Ponteiros não guardam valores, apenas endereços de memória, ou seja, se atribuímos um valor ao ponteiro, esse valor será um novo endereço de memória.

Ex.ptr1 = &var1; ptr1 = 100;

Nós mudamos o endereço de memória que ptr1 está apontando, agora ele não aponta mais para o endereço devar1, e sim, para o endereço 100. Mas, o que tem no endereço 0x100 ? Esse é um erro muito comum.

Inicializar um ponteiro com o valor de uma dereferência.

Ex.int *ptr1 = *var1;.

Esses são alguns dos erros mais comuns, embora praticamente todos os compiladores são capazes de impedir que eles ocorram.

Creative Commons License
Autor: Denys William Xavier
Este artigo está sob Licença Creative Commons.

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *