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ê!

Apontadores

Declaração de um ponteiro

Exercícios Resolvidos

Exercício Resolvido #1

Explique o que é um ponteiro em uma linguagem de programação.

Passo 1

Um ponteiro nada mais é do que um endereço de memória. Quando trabalhamos com um ponteiro estamos trabalhando com um endereço que “aponta” para algum lugar da memória RAM que contém algum dado que será usado em nosso programa.

Resposta

Ei, a resposta está no passo a passo :)

Exercício Resolvido #2

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 #3

Faça a declaração de um ponteiro do tipo ponto flutuante chamado p t r F l o a t .

Passo 1

Para realizarmos a declaração de um ponteiro, basta sinalizarmos o tipo que iremos apontar e utilizarmos o operador * seguido do nome do ponteiro.

Resposta

Ei, a resposta está no passo a passo :)

Exercício Resolvido #4

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 .

Exercício Resolvido #5

Analise a seguinte estrutura:

Crie um ponteiro para a estrutura i n f P e s s o a i s chamado r o b e r t o .

Passo 1

Para criarmos esse ponteiro precisamos nos atentar a redefinição de tipo que ocorre na linha 08 do código, nela podemos observar a atribuição do “apelido” p e s s o a a estrutura i n f P e s s o a i s .

Passo 2

Agora que já sabemos que podemos utilizar a denominação p e s s o a para nos referirmos a estrutura, basta declararmos o ponteiro.

Para isso, basta informarmos o tipo da estrutura, que nesse caso é pessoa, seguido do operador * e do nome do ponteiro, que segundo o enunciado deve ser r o b e r t o .

Resposta

Ei, a resposta está no passo a passo :)

Exercício Resolvido #6

Analise o seguinte trecho de código:

O que impede esse programa de ser compilado corretamente?

Passo 1

O problema desse programa está na linha 04, isso acontece, pois, a inicialização do ponteiro p t r I n t está sendo realizada diretamente com o valor armazenado pela variável x e não com o endereço dessa variável na memória.

Passo 2

Sendo assim, para arrumarmos esse problema basta colocarmos o operador & antes da variável x .

Essa simples mudança fará com que o endereço da variável x seja atribuído ao ponteiro p t r I n t e não o eu valor armazenado (causador do erro).

Resposta

Ei, a resposta está no passo a passo :)

Exercício Resolvido #7

Observe a seguinte expressão:

O que é do tipo float?

  1. A variável p o n t ;
  2. O endereço de p o n t ;
  3. A variável apontada por p o n t ;
  4. Nenhuma das anteriores.

Passo 1

O tipo utilizado na declaração de um ponteiro é utilizado para indicar o tipo do dado que será apontado pelo endereço armazenado por esse ponteiro.

Passo 2

Como esse dado estará armazenado na memória, esse endereço representa uma variável (recurso de alocação das linguagens de programação) e por isso o item correto é a letra c).

Resposta

Ei, a resposta está no passo a passo :)

Exercício Resolvido #8

Analise as seguintes expressões:

Qual delas é a correta para a declaração de um ponteiro na linguagem C?

Passo 1

A 2º expressão é a correta para a declaração de um ponteiro na linguagem C.

Passo 2

Basicamente, nós primeiro dizemos para o programa o tipo do dado que será apontado pelo endereço que será armazenado pelo ponteiro sendo declarado, depois nós simplesmente utilizamos o operador * para sinalizar que estamos criando um ponteiro e não uma variável comum de tal tipo, por fim nós criamos o nome do ponteiro sendo declarado.

Resposta

Ei, a resposta está no passo a passo :)