300x250 AD TOP

Blogger news

AD (728x90)

Tecnologia do Blogger.

Colaboradores

Seguidores

Postagens populares

Tagged under:

Linguagem C - Ponteiros








Ponteiros em C, para muitos uma grande dor de cabeça, o assunto que faz a nota diminuir, aquele assunto que deve ser estudado, porque com certeza vai constar na prova. São diversos os impedimentos mentais que são criados para bloquear a mente para não aprender esse assunto, com certeza você teve conhecer algum colega de faculdade que já te disse isso, porém relaxa, não liga pra ele, ponteiro não é nenhum bicho de sete cabeças, muito pelo contrário, ponteiros vieram para te dar uma total liberdade para fazer o que você quiser, sem gastar muita memória do computador, entenda o que ponteiros e faça a diferença.

Certo, depois da leve motivação, vamos ao que interessa.

Considere esta declaração:

int i = 100; 
O que esta declaração diz ao compilador?
Ela diz para o compilador reservar espaço na memória para armazenar um valor inteiro, associando o nome “i” a esse espaço de memória e por fim armazena o valor 100 nesta localização.

O imagem abaixo ilustra o que acabei de descrever.




Nota:
Para acessar o endereço de memória de uma variável, utilizamos o operador & a esquerda da variável que se deseja conhecer o endereço de memória.

Uma boa exemplificação do que acabou de ser dito é o código seguinte.

#include "stdio.h" 
int main(int argc, char const *argv[]){ 
 int i = 100; 
 printf("Endereco de i: %p\n", &i); 
 printf("Valor de i: %d\n", i); 
}
Saída: Endereco de i: 0xbff6f36c
Valor de i: 100

Acho que o seu professor já deve ter lhe tido como funciona o endereçamento de memória de um computador, porém por via das dúvidas darei um breve resumo.

A memória de qualquer computador é uma sequência de bytes, onde cada byte pode armazenar um número inteiro entre o e 255, sendo cada byte na memória identificado por um endereço numérico, independente do conteúdo. Mas uma vez segue logo abaixo uma imagem para ilustra o que acabou de ser dito.


 
Cada objeto(variável, strings, vetores, etc.) que reside na memória do computador ocupa um certo número de bytes, e a melhor forma de saber quantos bytes uma objeto ocupa na memoria é utilizar sizeof da seguinte forma.
#include "stdio.h" 
int main(int argc, char const *argv[]){ 

 printf("[int] %d bytes consecutivos\n", sizeof(int)); 
 printf("[char] %d byte\n", sizeof(char)); 
 printf("[float] %d bytes consecutivos\n", sizeof(float)); 
} 
 
Saída : [int] 4 bytes consecutivos
[char] 1 byte
[float] 4 bytes consecutivos

Quantos bytes consecutivos tem um float[4]?

Um dica que o meu professor me deu e venho repassar aqui, é que devemos ter sempre na mente as características básicas de uma variável: tipo, endereço de memória e valor. Tendo em mente essas características será fácil perceber que ponteiros não são coisas de outro mundo.

Vamos ao tão esperado momento, o que é um ponteiro?

Um ponteiro (apontador ou pointer) é um tipo especial de variável cujo valor armazenado é um endereço de memória.

Um ponteiro pode, e deve pode questão de boas praticas, ter o valor NULL, quando não contém nenhum endereço.

Nota: a constante NULL é definida na biblioteca stdlib.h, traduzindo importe a essa biblioteca o inicio do programa.
Como declarar um ponteiro?

Semelhante a forma de como é declarado um variável comum, o ponteiro apresenta apenas uma pequena diferença.

Sintaxe:

<tipo_da_variavel> *<nome_da _variavel>;

Exemplo:

int *i; //Um ponteiro de inteiro
char *c; // Um ponteiro de char 
float *x; // Um ponteiro de float

Todas as variáveis criadas no exemplo acima são ponteiros e portanto guardam apenas endereços de memória.

Nota: O símbolo * é conhecido como operador de indireção, e serve tanto para informa ao compilador que desejamos alocar espaço para um ponteiro, quanto para acessar ou modificar o conteúdo do mesmo.

Observe a ilustração abaixo de funcionamento do ponteiro.



Com o tempo você vai perceber que essa simples imagem diz muitas coisas sobre a grande eficácia dos ponteiros, mas caso você não tenha percebido, relaxe tenho um exemplo que mostra a eficiência da utilização de ponteiros.

Imagine que o seu professor pedisse que você implementasse uma função troca(valor1, valor2) que apenas invertesse os valores de duas variáveis passadas por parâmetro.

Se você não conhecesse ponteiros, você poderia pensar em uma solução como esta:

#include "stdio.h" 
void troca(int a, int b){ 
 int temp; 
 temp = a; 
 a = b; 
 b = temp; 
} 

int main(int argc, char const *argv[]){ 
 int a = 5; 
 int b = 10; 
 troca(a, b); 
 printf("a: %d  b: %d\n",a, b); 
}  
Saída: a: 5 b: 10

Esta saída não é a correta e consequentemente o programa está errado, já que função troca de nada serviu, então você pensa, a lógica aparentemente está correta, por que está dando errado? Isso deve ser loucura do C.

A responta para a sua indagação é bem simples, você fez uma passagem de parâmetro por valor no qual foi criada um cópia do valor passado, nesse caso o 5 e o 10 e todas as alterações acorridas dentro do escopo da função ficam restritas a função.

O solução correta para esse problema é utilizar a passagem de parâmetro por referência, no qual não é criada uma cópia do valor da variável.

Então você me pergunta, como utilizar passagem de parâmetro por referência em C?
Simples, utilizando ponteiros, o código abaixo resolve os seus problemas.

#include "stdio.h" 
void troca(int *a, int *b){ //Note que agora os parâmetros são ponteiros
 int temp; 
 temp = *a; // * a esquerda da variável como já foi dito serve para pegar ou alterar o valor.
 *a = *b; 
 *b = temp; 
} 

int main(int argc, char const *argv[]){ 
 int a = 5; 
 int b = 10; 
 troca(&a, &b); //& a esquerda da variável serve para pegar o endereço de memória.
 printf("a: %d  b: %d\n",a, b); 
} 
Saída: a: 10 b: 5

Agora sim a função troca está funcionando como esperado, tudo isso graças aos ponteiros, este foi apenas um pequeno exemplo das maravilhas que podem ser feitas com ponteiros, até a próxima, Tchau.

4 comentários: