Вы находитесь на странице: 1из 5

10 Noes bsicas de alocao dinmica de memria

10.1 O que alocao dinmica


At agora, os programas utilizavam a memria do computador estaticamente: todas as posies de memria eram reservadas para as variveis no incio da execuo do programa ou da funo e, mesmo que no estivessem sendo mais utilizadas, continuavam reservadas para as mesmas variveis at a concluso da execuo do programa ou da funo. Um vetor global do tipo float com dez mil componentes, por exemplo, ocupar quarenta mil bytes de memria durante toda a execuo do programa. Naturalmente, isto pode, em grandes programas, sobrecarregar ou, at mesmo, esgotar a memria disponvel. No primeiro caso, h uma degradao na eficincia do programa; no segundo caso a execuo do programa pode ser inviabilizada. Os compiladores C permitem a alocao dinmica da memria de tal modo que posies de memria sejam reservadas para variveis no instante em que sejam necessrias e sejam liberadas (as posies de memria) para o sistema nos instantes em que no estejam sendo utilizadas. A alocao dinmica de memria pode ser feita atravs das funes malloc(), calloc() e realloc() cujos prottipos se encontram no arquivo alloc.h e so os seguintes void *malloc(size_t Tam); void *calloc(size_t NumItens, size_t Tam); void *realloc(void *Bloco, size_t Tam); A, size_t um tipo de dado pr-definido, definido tambm no arquivo alloc.h, Tam o nmero de bytes que se pretende alocar dinamicamente, NumItens a quantidade de itens de Tam bytes que se pretende alocar e Bloco um ponteiro que contm o endereo da varivel cuja memria se pretende expandir em Tam bytes. A funo malloc() retorna um ponteiro para um bloco de Tam bytes at ento disponvel, a funo calloc() retorna um ponteiro para um espao de memria at ento disponvel capaz de armazenar NumItens objetos, cada um deles com Tam bytes e a funo realloc() retorna um ponteiro para um bloco de memria com quantidade de bytes igual soma algbrica da quantidade de bytes apontada por Bloco e Tam, podendo Tam ser negativo. Caso a quantidade de bytes pretendida no esteja disponvel, as funes acima retornam NULL. Como os ponteiros retornados so ambos do tipo void, eles devem ser moldados para poderem receber endereos de qualquer tipo de varivel. Por exemplo, o programa #include <stdio.h> #include <alloc.h> main() { int *v, t; v = (int *)malloc(80); if (v == NULL) printf("Memoria nao disponivel"); else { for (t = 0; t <= 40; t = t + 1) v[t] = t*t; for (t = 0; t <= 40; t = t + 1) printf("%d ", v[t]); free(v); } } armazena os quadrados dos quarenta primeiros nmeros inteiros num vetor criado dinamicamente. A funo free() libera para o sistema a quantidade de memria alocada para o seu argumento por uma das funes malloc(), calloc() ou realloc(). Naturalmente, o leitor pode estar pensando que o programa acima no teria muita vantagem em

relao ao programa abaixo, onde o vetor v criado estaticamente, #include <stdio.h> main() { int v[40], t; for (t = 0; v <= 40; t = t + 1) v[t] = t * t; for (t = 0; v <= 40; t = t + 1) printf("%d ", v[t]) } De fato, os dois programas durante suas execues utilizam oitenta bytes de memria. Haver diferena se estes programas fizerem parte de um programa maior. Neste caso, o primeiro utiliza oitenta bytes apenas at a execuo do comando free(), enquanto que o segundo utiliza os oitenta bytes durante toda execuo do programa. Naturalmente, tambm, o leitor pode estar se perguntando qual a vantagem do primeiro dos programas acima em relao ao programa #include <stdio.h> main() { int *v, t; for (t = 0; v <= 40; t = t + 1) v[t] = t * t; for (t = 0; v <= 40; t = t + 1) printf("%d ", v[t]) } no qual o "tamanho" de v no foi fixado e portanto no h "desperdcio" de memria. O que ocorre que no primeiro se no houver memria disponvel, o vetor v no "criado", cabendo ao programador ajustar o programa para esta hiptese.

10.2 Armazenando dinamicamente um polinmio


A funo realloc() aumenta a eficincia de utilizao de memria pelo fato de que a quantidade de memria alocada para um vetor pode crescer medida da necessidade. Para exemplificar, imagine a funo abaixo que "l um polinmio" p(x). Como se sabe, um polinmio p(x) = a 0xn + a1xn-1 + ... + an-1x + an identificado pelo seu grau e pelos valores de seus coeficientes. Se se pretende que o grau no seja dado de entrada, a questo a mesma que ocorre quando se trabalha com uma relao de nmeros: no se sabe a quantidade deles e, portanto, no se pode precisar o tamanho do vetor necessrio. Uma soluo utilizar a funo malloc() para inicializar um ponteiro e, medida que os coeficientes so digitados, utilizar a funo realloc() para expandir a memria necessria. #include <stdio.h> #include <alloc.h> #include <string.h> #include <stdlib.h> int LePolinomio(int *p) { char *Coef; int i; printf("Digite os coeficientes ('fim' para encerrar)\n"); i = 1; do { p = (int *)realloc(p, 2*i);

gets(Coef); if (strcmp(Coef, "fim") != 0) { p[i - 1] = atof(Coef); i = i + 1; } } while (strcmp(Coef, "fim") != 0); free(p); return (i - 1); } A "inicializao de p" deve ocorrer antes da chamada da funo. Por exemplo, na funo main() atravs do ponteiro declarado nesta funo e que ser passado para a funo LePolinomio(). main() { int *Poli; int Grau; Poli = (int *)malloc(2); Grau = LePolinomio(Poli); ... } Observe que optamos por dar entrada nos coeficientes como strings. Esta opo foi feita para que pudssemos usar "fim" como flag, j que a utilizao de qualquer nmero com esta finalidade fica complicada j que qualquer nmero pode ser um coeficiente de um polinmio.

10.3 Listas
Para mais um exemplo de alocao dinmica, apresentaremos um tipo de dado chamado lista simplesmente encadeada. Este tipo de dado pode ser definido como uma sequncia de elementos ligados atravs de ponteiros com um nmero mximo de elementos no fixado a priori. Usualmente, cada elemento da lista uma estrutura, com um campo contendo um ponteiro e os demais campos contendo os dados que o programa vai manipular. Associa-se um ponteiro ao primeiro elemento e o campo do tipo ponteiro do ltimo elemento da lista tem valor NULL. O ponteiro que aponta para o primeiro elemento da lista indica o seu incio e o valor do ponteiro da ltima estrutura da lista ser NULL indicar o seu final. Para as funes que vamos apresentar (criao de uma lista de inteiros, exibio e remoo de um elemento desta lista) necessitamos definir a seguinte estrutura: struct TElemento { int Valor; struct TElemento *p; }; Observe que na definio de uma estrutura possvel se definir um campo de tipo idntico ao da estrutura. Este campo definir um ponteiro que aponta para o elemento seguinte da lista e o campo Valor armazenar o inteiro. Necessitamos tambm de duas variveis globais: struct TElemento *Inicio, *Prox; a varivel Inicio para apontar para o inicio da lista e Prox para apontar para o prximo elemento. necessrio observar que o ponteiro Inicio aponta para o ltimo elemento que foi inserido na lista, enquanto que o campo *p do primeiro elemento da lista igual a NULL. Para criar a lista fazemos Inicio receber NULL e, dentro de uma estrutura de repetio, alocamos memria para o ponteiro Prox, damos entrada em Prox.Valor e fazemos o campo p de Prox receber Inicio e

Inicio receber Prox para que este ponteiro aponte sempre para o ltimo elemento a dar entrada. Temos a seguinte funo: void CriaLista() { Inicio = NULL; printf("Digite os numeros (-1 para encerrar)\n"); do { Prox = (struct TElemento *)malloc(5); scanf("%d",&(*Prox).Valor); if ((*Prox).Valor != -1) { (*Prox).p = Inicio; Inicio = Prox; } } while ((*Prox).Valor != -1); } Para exibir a lista (ou realizar nela qualquer processamento), basta percorr-la desde seu incio (Prox = Inicio) at o seu final ((*Prox).p = NULL). void ExibeLista() { Prox = Inicio; while (Prox != NULL) { printf("%d ", (*Prox).Valor); Prox = (*Prox).p; } printf("\n"); } Para deletar um elemento da lista necessrio que, quando ele for localizado, se armazene o ponteiro do elemento anterior a ele e o ponteiro que aponta para ele. Se o elemento a ser deletado for o primeiro, basta fazer Inicio apontar para o segundo elemento; se o elemento a ser excludo for outro elemento, basta fazer o ponteiro do elemento anterior para o elemento seguinte e devolver ao sistema a posio de memria ocupada pelo elemento a ser excludo. void Deleta(int n) { struct TElemento *Ant; Prox = Inicio; Ant = Inicio; while ((Prox != NULL) && ((*Prox).Valor != n)) { Ant = Prox; Prox = (*Prox).p; } if (Prox != NULL) { if ((Ant == Inicio) && (Prox == Inicio)) Inicio = (*Prox).p; else (*Ant).p = (*Prox).p; free(Prox); } else printf("Elemento nao esta lista \n");

10.4 Exerccios propostos


1. Escreva uma funo que calcule a mdia de uma relao de nmeros armazenada numa lista criada pela funo CriaLista() acima. 2. Escreva uma funo que insira um elemento numa lista ordenada de modo que a lista permanea ordenada.
Observao Propostas de solues dos exerccios propostos podem ser solicitadas atravs de mensagem eletrnica para jaime@ccen.ufal.br com assunto RESPOSTAS LIVRO C, anexando o formulrio abaixo devidamente preenchido. Nome
1 2

Categoria1

Instituio2

Curso2

Cidade/Estado

Categoria: docente, estudante, autodidata Se docente ou estudante

Вам также может понравиться