Por exemplo, o código a seguir demonstra o uso mais simples possível da pilha:
int main()
{
int *p;
p = (int *)malloc(sizeof(int));
if (p == 0)
{
printf("ERRO: Sem memória\n");
return 1;
}
*p = 5;
printf("&d\n", *p);
free(p);
return 0;
}
A primeira linha neste programa invoca a função malloc. Esta função faz três coisas:

O programa então verifica o ponteiro para garantir que a solicitação de alocação ocorreu com a linha if (p == 0) (que também poderia ter sido escrita como if (p == NULL) ou mesmo if (!p) Em caso de falha da alocação (se p for zero) o programa encerra. Em caso de êxito na alocação, o programa inicializa o bloco com o valor 5, imprime o valor e executa a função free para retornar a memória à pilha antes do programa encerrar.
Não existe diferença entre este código e o código anterior que determine p igual ao endereço de um inteiro existente i. A única distinção é que, no caso da variável i, a memória existiu como parte do espaço de memória pré-alocado do programa e tem dois nomes: i e *p. No caso da memória alocada da pilha, o bloco tem o único nome de *p e é alocado durante a execução do programa. Duas dúvidas comuns:
void main()
{
int *p, *q;
p = (int *)malloc(sizeof(int));
q = p;
*p = 10;
priprintf("%d\n", *q);
*q = 20; pr
printf("%d\n", *q);
}
O resultado final deste código seria 10 n linha 4 e 20 na linha 6. Eis um diagrama:

O seguinte código é um pouco diferente:
void main()
{
int *p, *q;
p = (int *)malloc(sizeof(int));
q = (int *)malloc(sizeof(int));
*p = 10;
*q = 20;
*p = *q;
prprintf("%d\n", *p);
}
O resultado final deste código seria 20 na linha 6. Eis um diagrama:

Observe que o compilador permitirá *p = *q pois *p e *q são ambos inteiros. Esta instrução diz: "Mova o valor inteiro apontado por q em um valor inteiro apontado por p". A instrução move os valores. O compilador também permitirá p = q, pois p e q são ambos ponteiros e apontam para o mesmo tipo (se s for um ponteiro para um caractere, p = s não é permitido pois eles apontam para tipos diferentes). A instrução p = q diz: "Aponte p para o mesmo bloco para o qual q aponta". Em outras palavras, o endereço apontado por q é transferido para p, assim ambos apontam para o mesmo bloco. Esta instrução transfere os endereços.
De todos estes exemplos, você pode ver que há quatro modos diferentes para inicializar um ponteiro. Quando um ponteiro é declarado, como em int *p, ele inicia no programa em um estado não inicializado. Como ele pode apontar para qualquer lugar, remover sua referência é um erro. A inicialização de uma variável de ponteiro envolve apontá-la para um local conhecido na memória.
p = 0;
ou:
p = NULL;
O que isto faz fisicamente é colocar um zero em p. O endereço do ponteiro p é zero. Isso é geralmente diagramado como:

if (p == 0)
{
...
}
ou:
while (p != 0)
{
...
}
O sistema também reconhece o valor zero e gerará mensagens de erro se você remover a referência de um ponteiro zero. Por exemplo, no seguinte código:
p = 0; *p = 5;
O programa geralmente travará. O ponteiro p não aponta para um bloco, aponta para zero, assim um valor não pode ser atribuído a *p. O ponteiro zero será usado como sinalizador quando chegarmos às listas vinculadas.
O comando malloc é usado para alocar um bloco de memória. Também é possível desalocar um bloco de memória quando ele não é mais necessário. Quando um bloco é desalocado, ele pode ser reutilizado por um comando malloc subseqüente que permite ao sistema reciclar a memória. O comando usado para desalocar a memória é chamado free e aceita um ponteiro como seu parâmetro. O comando free faz duas coisas:
O exemplo a seguir mostra como usar a pilha: ele aloca um bloco de inteiros, preenche, escreve e o descarta:
#include <stdio.h>
int main()
{
int *p;
p = (int *)malloc(sizeof(int));
*p=10;
printf("%d\n",*p);
free(p);
return 0;
}
Este código só é útil para demonstrar o processo de alocação, desalocação e como usar um bloco em C. A linha malloc aloca um bloco de memória do tamanho especificado - neste caso, sizeof(int) bytes (4 bytes). O comando sizeof em C retorna o tamanho, em bytes, de qualquer tipo. A codificação poderia ter dito malloc(4), uma vez que sizeof(int) é igual a 4 bytes na maioria das máquinas. Todavia, o uso de sizeof torna a codificação mais portátil e legível.
A função malloc retorna um ponteiro para o bloco alocado. Este ponteiro é genérico. O uso do ponteiro sem conversão de tipo geralmente produz um tipo de aviso do compilador. O (int *) converte o ponteiro genérico retornado por malloc em um "ponteiro para um número inteiro", que é esperado por p. A instrução free em C retorna um bloco para a pilha para reutilização.
O segundo exemplo ilustra as mesmas funções que o exemplo anterior, mas usa uma estrutura em vez de um inteiro. Em C, o código se parece com:
#include<stdio.h> struct rec { int i; float f; char c; }; int main() { struct rec *p; p=(struct rec *) malloc (sizeof(struct rec)); (*p).i=10; (*p).f=3.14; (*p).c='a'; printf("%d %f %c\n",(*p).i,(*p).f,(*p).c); free(p); return 0; }
Observe a seguinte linha:
(*p).i=10;
Muitos se perguntam por que não funciona:
*p.i=10;
A resposta está relacionada com a precedência de operadores em C. O resultado do cálculo 5+3*4 é 17, e não 32, pois o operador * tem maior precedência do que + na maioria das linguagens de computação. Em C, o operador . tem precedência maior que *, portanto os parênteses forçam a devida precedência.
A maioria das pessoas se cansa de digitar (*p).i o tempo todo, de forma que o C oferece uma anotação de taquigrafia. As duas instruções a seguir são equivalentes, porém a segunda é mais fácil de digitar:
(*p).i=10; p->i=10;
Você verá a segunda instrução mais freqüentemente do que a primeira ao ler a codificação de outras pessoas.
| FAVORITOS | |||||
| Faça do HowStuffWorks a sua página inicial | | | digg it! (?) | | | del.icio.us | |