Aula 2.17 - Ponteiros em C
Nesta aula você aprenderá definitivamente o que são ponteiros e como utilizá-los. Vamos lá!
Ponteiros são variáveis que armazenam endereços. Você deve estar se perguntando "mas que endereço?", antes precisamos definir alguns conceitos básicos.
A memória do computador (memória RAM) é composta por uma sequência de bytes, em que cada byte é capaz de armazenar entre 1 e 256 possíveis valores. Sendo assim ao declarar uma variável, ela ocupará uma certa quantidade de bytes na memória.
A imagem acima ilustra quantos bytes cada tipo de variável ocupa, acesse a Aula 2.2 caso queira saber mais como obter essas informações.
Como os bytes da memória são numerados sequencialmente, cada um desses bytes ocupa uma posição identificada por um número único variando de 0 à totalidade de bytes da memória RAM do seu computador. Este número único recebe o nome de endereço, assim cada objeto colocado na memória terá um endereço.
O endereço em C é dado pelo operador &, por isso ao ler uma variável com scanf você utiliza do &. Exemplo:
scanf("%d",&b);
Assim você avisa ao compilador que você quer colocar o valor digitado pelo usuário no endereço da variável b.
Suponha que você precisa guardar o endereço da variável b, como fazer isso? Bem simples.. utilize ponteiros! A sintaxe de declaração de ponteiro é a seguinte:
tipo *p
Onde 'p' é o nome da sua variável ponteiro, ou seja, pode utilizar outros nomes.
Confira a imagem abaixo:
Como pode observar, a variável 'a' armazenou o endereço de 'b' e portanto ao usar o símbolo *a (lê-se apontado por 'a') é exibido o que temos em 'b'. Na imagem acima os endereços foram impresso como inteiro, mas você pode utilizar do %p no lugar do %d para imprimir em formato de endereço.
Pode ser que exista situações em que você precisa declarar um ponteiro e você não quer que ele aponte para lugar nenhum, para isso basta colocá-lo apontando para NULL.
Exemplo: int *a = NULL;
Você pode utilizar ponteiro em funções para manipular valores contidos em certos endereços na memória. Exemplo:
Como ilustra a imagem acima, foi possível trocar os valores entre a e b em uma função, note que a função não recebe os valores de 'a' e 'b', mas sim o endereço das duas variáveis permitindo assim manipular seus valores. Note que na função troca() foi criado 2 ponteiros para receber o endereço de a e b da função principal main().
Agora vamos compreender a relação entre ponteiros e vetores, para isso espero que tenha acompanhado a Aula 2.10 ou que já saiba vetores. Portando já deve saber que o nome de um vetor corresponde a posição do primeiro elemento desse vetor, logo o nome desse vetor é nada mais que o endereço do primeiro elemento do vetor.
Existem duas formas de criar um ponteiro apontando para o primeiro elemento de um vetor, sendo p um ponteiro: int *p;
Podemos apontar assim: p = &vetor[0];
ou assim: p = vetor;
O nome de um vetor apontará eternamente para o primeiro elemento desse vetor, mas um ponteiro como o ponteiro 'p' do exemplo acima, pode apontar para qualquer posição desse vetor. Exemplo:
p = &vetor[2];
Tendo isso em mente, você conseguirá fazer operações aritmética com ponteiros. Como o que ponteiros armazenam é posições da memória, se você fazer operações de incremento ou decremento com ponteiros, na verdade você está avançando ou retrocedendo posições da memória.
Suponha um ponteiro "p" para inteiro que está apontando para a posição 121145768, se você realizar operação de incremento .. "p+1" significa que este ponteiro, em um computador em que a arquitetura determina que um inteiro seja 2 bytes, avançará dois bytes ou seja se pedir para imprimir o que p+1 está apontando, ele irá retornar o que tem na posição 121145770 da memória.
Também é possível saber quantos elementos existem entre dois ponteiros utilizando da operação de diferença. Assim, por exemplo, o comprimento de um string fazendo a posição do '\0' de uma string menos o ponteiro, mas fique atento que isso só é possível entre ponteiros do mesmo tipo, no exemplo ponteiros do tipo char.
Você sabia que é possível criar um ponteiro que aponte para um ponteiro? Exemplo:
int x; //uma variável que receber um inteiro qualquer
int * ptr_x; //um ponteiro para armazenar o endereço da variável x
int ** ptr_ptr_x; //um ponteiro que armazenar o endereço do ponteiro de x
Confuso né? Confira como fica na imagem do programa abaixo:
Como podem observar, foi impresso o conteúdo e endereço de x apontado pelos ponteiros.
Espero que tenha compreendido ponteiros, nos vemos na próxima aula!
>> Próxima aula, clique aqui.
COMENTÁRIOS