Entendendo ponteiros e a função malloc
9 Outubro 2007
Bem, algum tempo atrás estava eu brincando com C criando uma função para retornar todos os números primos menores do que um determinado número, e eu queria que a função cria-se o vetor com os primos e passa-se para main, mas para fazer isso precisava entender um pouco melhor essa tecnologia estranha, malloc e conseqüentemente: ponteiros e a função free().
Vamos começar pelos ponteiros. Declarando ponteiros:
int *ponteiro;
Bem simples, só colocar um asterisco na frente do nome da variável e temos um ponteiro, próximo passo, entender como ele funciona.
Um ponteiro aponta, quem aponta, aponta para algo, um ponteiro aponta para uma variável, desse jeito:
ponteiro = &variavel;
Pronto, nosso ponteiro já tem para quem apontar(quando o ponteiro é iniciado ele aponta para algum lugar aleatório da memória) ou em outras palavras, o nosso ponteiro tem uma referência para a variavel:
ponteiro -> variavel
Mas agora, por que do “&”? Bem, uma variável armazena conteúdo, o conteúdo é armazenado na memória principal do computador(ram), e para se saber onde que esta armazenado o valor da variável na memória ram “nós”(o computador) temos que saber aonde que a variável esta na memória, para isso existe uma tabela, na própria memória ram, com o nome da variável e o endereço da mesma(rua, bairro, telefone, essas coisas assim =D), e em C, o endereço de uma variável é:
&variavel;
Depois que nós apontamos para a variável nós podemos modifica-la, mas não com essa sintaxe:
ponteiro = 5;
Afinal, o valor do ponteiro é o endereço na memória da variável para que ele esta apontando, se nós usarmos essa sintaxe acima, nós mudaremos para quem se aponta, não o valor de quem se aponta, aqui entra a segunda sintaxe:
*ponteiro = 5;
Pronto, problema resolvido, agora conseguimos modificar o valor para quem se aponta sem maiores problemas.
Uma revisãozinha antes de continuar, nós declaramos um ponteiro usando um asterisco na frente do nome do ponteiro(int *ponteiro;) o valor do ponteiro é um endereço de memória (ponteiro = &variavel;) e a partir do ponteiro nos conseguimos modificar o valor da variável para a qual se aponta(*ponteiro = 5;).
Aleluia, terminamos os ponteiros, agora podemos entender a função malloc:
#include <stdlib.h>
void *malloc(size_t size);
Bem, acima temos o protótipo da função e o include para a biblioteca que contem a função, o que para mim não faz nenhum sentido sem exemplo, então vamos para o exemplo:
ponteiro = (int *)malloc (sizeof(int)*5);
Ali nós tivemos que usar uma segunda função, sizeof() – ela passa o tamanho em bytes de um tipo de dados, no caso é um inteiro porque o nosso ponteiro é um ponteiro para inteiros (int *ponteiro;), para armazenar a quantidade correta de bytes , depois o valor de bytes é multiplicado por 5, que é o número de casas que eu quero para o vetor, a função vai alocar esse espaço na memória e passar o endereço da memória que é atribuído ao ponteiro, simples assim.
Agora algumas notas:
A parte no membro direito na frente da palavra malloc “(int *)” não é obrigatória para todos os compiladores, porem, mesmo se não for necessário no compilador que você usa é uma boa pratica coloca-lo no código aumentando a compatibilidade entre C e C++ e não irá resultar em erro em outros compiladores.
A função malloc não “oferece” uma variável do tamanho desejado, ela oferece um vetor do tamanho desejado(dentro de certos limites físicos[a memória ram]), tamanho que é igual ao número que está multiplicando(no caso 5), e ela não é infalível, infelizmente memória acaba, então é sempre uma boa pratica testar se o valor do ponteiro é diferente de NULL, afinal de contas, não queremos nenhum problema com os nossos programas:
intenger = (int *)malloc(sizeof(int)*5);
if(intenger == NULL){
exit(EXIT_FAILURE);
}
Outra nota importante, ponteiros apontam para variáveis, não para vetores, e isso trás uma importante implicação, o valor da memoria passado pela função malloc é o endereço do índice zero do vetor, então nós temos o seguinte:
ponteiro = vetor[0]
ponteiro + 1 = vetor[1]
ponteiro + 2 = vetor[2]
ponteiro + 3 = vetor[3]
ponteiro + 4 = vetor[4]
Assim quando você quiser modificar o próximo índice no vetor de usar a seguinte sintaxe:
*(ponteiro + 1) = 5;
Isso é chamada de aritimética de ponteiros, o compilador deve saber que o ponteiro é um inteiro, pela sua declaração, assim ele sabe qual é o tamanho em bites do seu inteiro – valor esse que eu não vou mencionar, pois é diferente de arquitetura para arquitetura – assim quando se adiciona 1 ao ponteiro, o compilador sabe que se deve pular o equivalente ao tamanho de um inteiro a partir do primeiro valor, chegando ao segundo:
——————————–V int + 1————
|0101110110110110|0111010101111011|
^ int————————————————
Isso trás algumas coisas a tona, cuidado com a aritimética de ponteiros, pois se você tiver um vetor de 3 casas, e somar 3 ao ponteiro, você ira tentar acessar memória, talvez, restrita e resultara em um erro, segundo ponto a se notar é que a memoria alocada pelo malloc é continua, por isso a aritmética de ponteiros funciona.
Bem, agora nós já sabemos como usar os ponteiros e a função malloc(), agora temos mais três passos, entender a função free(), entender passagem por referência e por fim, a minha função primos() no próximo post.
Entry Filed under: C. .
5 Comments Add your own
Leave a Comment
Some HTML allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <pre> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>
Trackback this post | Subscribe to the comments via RSS Feed
1.
Fill | 8 Novembro 2007 at 11:19 pm
Cara seu post foi de grande ultilidade pra mim! Eu, estava quebrando a cabeça com ponteiros e alocação de memória… ;)
2. Free(), passagem por referência e a minha função « Avallon | 13 Janeiro 2008 at 7:24 pm
[...] 13 janeiro 2008 Continuando o artigo Entendendo ponteiros e a função malloc. [...]
3.
Cassio | 7 Abril 2008 at 9:44 am
Muito bom cara.
4.
Anderson Silva | 12 Junho 2009 at 3:30 am
Cara, parabens, bom tutorial, embora ainda não consigo entender esses negocios, tá complicado pra mim.
Parabens e Vlw….
5. malloc, uma nova abordagem « Avallon | 12 Junho 2009 at 2:54 pm
[...] Junho 2009 Faz algum tempo desde meu primeiro post sobre a função malloc, ele não esta muito bem estruturado ficando rasoavelmente inconpreensivel [...]