Introdução aos ponteiros

Ver Todos os Exercícios

Teoria

Introdução

Fala aí, aqui é o Guga do Responde Aí! Tudo bem com você?

Nesse tópico nós iremos conversar um pouquinho sobre um dos recursos mais importante da linguagem C até os dias atuais.

Certo, mas que recurso é esse?

Estamos nos referindo ao que chamamos de apontadores!

É por conta desse recurso que independente do dispositivo que você esteja usando para ler esse tópico, um programa na linguagem C está sendo executado (tem que ser algo muito bom mesmo para manter uma linguagem da década de 70 ainda ativa).

Nada mal, né?!

Apontadores

É claro que depois de criar todo esse hype você deve estar se perguntando sobre o que faz um apontador.

E por ser um grande amigo seu eu irei ser muito breve na explicação, um apontador ou ponteiro (utilizaremos ponteiro a partir de agora) é como se fosse uma variável que ao invés de armazenar um dado para o seu tipo, armazena o endereço de mémoria em que um dado do seu tipo está armazenado.

Vamos utilizar uma imagem para deixar as coisas mais simples:

Nessa imagem, mais precisamente no lado direito dela, nós podemos ver uma variável magic que armazena o número inteiro 111 (variável do tipo int).

Ainda no lado direito da imagem (referente a variável magic) nos podemos ver os seguintes números 0xE1 (na forma hexadecimal), que nada mais é que o endereço que a variável magic está armazenada na memória do computador. Vale lembrar que essa memória (RAM) é utilizada por todos os programas do computador e não só pelo programa em C que possui a variável magic, por isso endereços únicos são reservados para cada variável nessa memória.

Agora nós analisaremos o lado esquerdo da imagem, que onde temos um ponteiro para a variável magic (pointerToMagic). Ou seja, pointerToMagic é um ponteiro do tipo int, pois “aponta” para uma variável do tipo int. Além disso, podemos observar que o valor armazenado por esse ponteiro é 0xE1, que é justamente o endereço na memória em que a variável magic está armazenada.

Já ficou mais fácil de entender, né?

Para você não se esquecer desse conceito, lembre-se do termo apontador por se tratar de uma variável que aponta para alguma coisa através de seu endereço na memória. Ou se achar melhor, utilize o termo ponteiro, pois assim como em um relógio ele aponta para os números em um programa ele aponta para alguma coisa.

Nós utilizamos uma variável nesse exemplo, mas um apontador pode apontar para qualquer coisa que seja de mesmo tipo, isso vai desde os diferentes tipos primitivos de dados até structs e outras estruturas que vimos.

Declaração de um ponteiro

Para declararmos um ponteiro nós temos que ter o conhecimento de outros dois operadores da linguagem C, mas aprenderemos sobre eles de maneira prática. Então, observe o seguinte trecho de código:

Nele nós temos a declaração da variáveis magic vista anteriormente. Mas como declaramos pointerToMagic? A resposta está nesse outro trecho de código:

Onde nós temos o operador * (sim, o mesmo usado na multiplicação) que deve ser colocado após o tipo da variável para indicar que ela se trata de um ponteiro para um dado daquele tipo. Nesse caso, acabamos de declarar que pointerToMagic é um ponteiro para um dado do tipo int.

E o segundo operado é &, ele atua na inicialização do ponteiro pointerToMagic para dizer ao programa que estamos atribuindo ao ponteiro o endereço de memória da variável magic e não o conteúdo que ela armazena. Tanto que se o & não existisse um erro de tipo aconteceria, pois, o ponteiro espera um endereço de memória e não um número (usando esse caso como exemplo).

E para você ver que eu não estou mentindo, eu fiz um programa que faz essas duas declarações e imprime na tela o endereço de memória em que a variável magic está alocada e o valor armazenado por pointerToMagic.

Observe o resultado do programa na imagem a seguir:

E não é que os endereços são iguais mesmo!

Agora que já temos ciência do conceito de ponteiros, está na hora de resolvermos alguns exercícios de fixação!

Te espero na página aqui do ladinho.

Ah! Já ia me esquecendo, que a força esteja com você!

Declaração de um ponteiro

Exercícios Resolvidos

Exercício Resolvido #1

Crie um ponteiro para inteiro chamado p t r I n t e inicialize esse ponteiro com o endereço de uma variável chamada n I n t e i r o previamente inicializada com o valor 10.

Passo 1

A primeira coisa que nós temos que fazer é declarar e inicializar a variável n I n t e i r o com o valor 10.

Passo 2

Agora que já temos a variável n I n t e i r o , podemos declarar o ponteiro p t r I n t .

Para isso basta colocarmos o tipo do ponteiro, nesse caso int, o operador * seguido do nome do ponteiro. Quando nos referimos a inicialização do ponteiro, só precisamos utilizar o operador de igualdade seguido do operador & e do nome da variável que terá o seu endereço armazenado.

Resposta

Com isso temos o ponteiro p t r I n t armazenando o endereço da variável n I n t e i r o .

Exercício Resolvido #2

Analise o seguinte trecho de código:

O que o apontador d P t r F l o a t está armazenando?

Passo 1

Para descobrirmos isso teremos que analisar atentamente todas as declarações. Na linha 05, conseguimos perceber que d P t r F l o a t se trata de um ponteiro duplo para o tipo float inicializado com o endereço do ponteiro p t r F l o a t , que por sua vez é inicializado com o endereço da variável do tipo float n F l o a t que armazena o número 3,14.

Passo 2

Como um ponteiro duplo aponta para um endereço de um outro ponteiro, que por sua vez aponta para outro endereço, podemos concluir que o ponteiro duplo d P t r F l o a t armazena o endereço de memória do ponteiro p t r F l o a t , que por sua vez armazena o endereço de memória da variável n F l o a t .

Resposta

Logo, d P t r F l o a t armazena o endereço de memória do ponteiro p t r F l o a t .