Você está na página 1de 7

Anhanguera Educacional Estrutura de Dados - Prof. Ms.

Thiago Salhab Alves

Alocao Dinmica de Memria


At o momento, na declarao de um vetor para representar Listas, Filas e Pilhas, foi preciso dimension-lo, o que nos obrigava, a saber, de antemo, quanto espao seria necessrio, isto , tnhamos de prover o nmero mximo de elementos no vetor durante a codificao. Esse pr-dimensionamento um fator limitante. Por exemplo, se desenvolvermos um programa para calcular a mdia e a varincia das notas de uma prova, teremos de prever o nmero mximo de alunos. Uma soluo dimensionar o vetor com um nmero absurdamente alto, para no termos limitaes no momento da utilizao do programa. No entanto, isso levaria a um desperdcio de memria, o que inaceitvel em diversas aplicaes. Se, por outro lado, formos modestos no prdimensionamento do vetor, o uso do programa fica muito limitado, pois no conseguiramos tratar turmas com um nmero de alunos maior que o previsto. Felizmente, a linguagem C oferece meios de requisitar espaos de memria em tempo de execuo. Dizemos que podemos alocar memria dinamicamente. Com esse recurso, nosso programa para o clculo da mdia e varincia discutido antes pode, em tempo de execuo, consultar o nmero de alunos da turma e ento fazer a alocao do vetor dinamicamente, sem desperdcio de memria.

Uso da memria
Informalmente, podemos dizer que existem trs maneiras de reservar espao de memria para o armazenamento de informaes: A primeira usar variveis globais (e estticas). O espao reservado para uma varivel global existe quanto o programa estiver sendo executado. A segunda maneira usar variveis locais. Nesse caso, o espao existe apenas enquanto a funo que declarou a varivel est sendo executada, sendo liberado para outros usos quando a execuo da funo termina. Por esse motivo, a funo que chama no pode fazer referncia ao espao local da funo chamada. As variveis globais ou locais podem ser simples ou vetores. Para os vetores, precisamos informar o nmero mximo de elementos; caso contrrio, o compilador no saberia o tamanho do espao a ser reservado. A terceira maneira de reservar memria requisitar ao sistema, em tempo de execuo, um espao de um terminado tamanho. Esse espao alocado dinamicamente permanece

Anhanguera Educacional Estrutura de Dados - Prof. Ms. Thiago Salhab Alves reservado at que seja explicitamente liberado pelo programa. Por isso, podemos alocar dinamicamente um espao de memria em uma funo e acess-lo em outra. A partir do momento em que liberarmos o espao, ele estar disponibilizado para outros usos e no podemos mais acess-lo. Se o programa no liberar um espao alocado, ele ser automaticamente liberado quando a execuo do programa terminar. Na figura 1 abaixo, apresentamos um esquema didtico que ilustra de maneira fictcia a distribuio do uso da memria pelo sistema operacional. Quando requisitamos ao sistema operacional para executar um determinado programa, o cdigo em linguagem de mquina do programa deve ser carregado na memria. O sistema operacional reserva tambm os espaos necessrios para armazenar as variveis globais (e estticas) existentes no programa. O restante da memria livre utilizado pelas variveis locais e pelas variveis alocadas dinamicamente. Cada vez que uma determinada funo chamada, o sistema reserva o espao necessrio para as variveis locais da funo. Esse espao pertence pilha de execuo e, quando a funo termina, desempilhado. A parte da memria no ocupada pela pilha de execuo pode ser requisitada dinamicamente. Se a pilha tentar crescer alm do espao disponvel existente, dizemos que ela estourou, e o programa abortado com erro. Da mesma forma, se o espao de memria livre for menor do que o espao requisitado dinamicamente, a alocao no feita, e o programa pode prever um tratamento de erro adequado (por exemplo, podemos imprimir a mensagem Memria Insuficiente e interromper a execuo do programa). Cdigo do Programa Variveis Globais e Estticas Memria Alocada Dinamicamente

Memria Livre

Pilha

Anhanguera Educacional Estrutura de Dados - Prof. Ms. Thiago Salhab Alves Figura 1 Alocao Esquemtica de Memria

Funes da biblioteca padro


Existem funes, presentes na biblioteca padro stdlib, que permitem alocar e liberar memria dinamicamente. A funo bsica para alocar memria malloc. Ela recebe como parmetro o nmero de bytes que se deseja alocar e retorna o endereo inicial da rea da memria alocada. Para exemplificar, vamos considerar a alocao dinmica de um vetor de inteiros com 10 elementos. Como a funo malloc tem como valor de retorno o endereo da rea alocada e, nesse exemplo, desejamos armazenar valores inteiros nessa rea, devemos declarar um ponteiro de inteiro para receber o endereo inicial do espao alocado. O trecho de cdigo ento seria: int *v; v = malloc(10*4); Aps esse comando, se a alocao for bem sucedida, v armazenar o endereo inicial de uma rea contnua de memria suficiente para armazenar 10 valores inteiros. Podemos, ento, tratar v como tratamos um vetor declarado estaticamente, pois, se v aponta para o incio da rea alocada, sabemos que v[0] acessa o espao o primeiro elemento a ser armazenado, v[1] acessa o segundo, e assim por diante (at v[9]). No exemplo mostrado, consideremos que um inteiro ocupa 4 bytes. Para ficarmos independentes de compiladores e mquinas, usamos o operador sizeof(). v = malloc(10*sizeof(int)); Alm disso, devemos salientar que a funo malloc usada para alocar espao para armazenar valores de qualquer tipo. Por esse motivo, malloc retorna um ponteiro genrico, para um tipo qualquer, representado por void*, que pode ser convertido automaticamente pela linguagem para o tipo apropriado na atribuio. No entanto, comum fazer a converso utilizando o operador de molde de tipo (cast). O comando para a alocao do vetor de inteiros fica ento: v = (int*) malloc (10*sizeof(int)); Assim, o ponteiro v aponta para o endereo inicial de uma rea contnua de memria para 10 inteiros. O operador sizeof() obtm o tamanho em bytes do tipo int e o operador

Anhanguera Educacional Estrutura de Dados - Prof. Ms. Thiago Salhab Alves de cast (int*), converte o ponteiro genrico retornado por malloc para um ponteiro do tipo int*.A Figura 2 abaixo, ilustra de maneira esquemtica o que ocorre na memria. 1 Declarao: int *v Abre-se Espao na pilha para o ponteiro (varivel local)
Cdigo do Programa Variveis Globais e Estticas

2 Comando: v = (int*)malloc(10*sizeof(int)) Reserva espao de memria da rea livre e atribui endereo varivel
Cdigo do Programa Variveis Globais e Estticas 40 bytes

504

Livre

Livre

504

Figura 2 Alocao Dinmica de Memria Se, porventura, no houver espao livre suficiente para realizar a alocao, a funo retorna um endereo nulo (representado pelo smbolo NULL, definido em stdlib.h). Podemos cercar o erro na alocao da memria verificando o valor de retorno da funo malloc. Por exemplo, podemos imprimir uma mensagem e abortar o programa com a funo exit, tambm definida na stdlib. ... v = (int*) malloc (10*sizeof(int)); if (v == NULL) { printf(Memoria insuficiente.\n); exit(1); } ... Para liberar um espao de memria alocado dinamicamente, usamos a funo free. Essa funo recebe como parmetro o ponteiro da memria a ser liberada. Assim, para liberar o vetor v, fazemos:

Anhanguera Educacional Estrutura de Dados - Prof. Ms. Thiago Salhab Alves free (v); S podemos passar para a funo free um endereo de memria que tenha sido alocado dinamicamente. Devemos lembrar ainda que no podemos acessar o espao da memria depois de liberado. Para exemplificar o uso da alocao dinmica, o programa a seguir realiza o clculo da mdia e da varincia. O programa l o nmero de valores fornecidos, aloca um vetor dinamicamente, captura os valores e faz os clculos. #include <stdio.h> #include <conio.h> #include <stdlib.h> /* funo para clculo da mdia */ float media(int n, float *v) { int i; float s = 0.0f; for(i=0; i<n; i++) s += v[i]; return s/n; } /* funo para clculo da varincia */ float variancia(int n, float *v, float m) { int i; float s = 0.0f; for(i=0; i<n; i++) s += (v[i] - m) * (v[i] - m); return s/n; } main() { int i, n; float *v; float med, var; printf("Quantas notas sero lidas?: "); scanf("%i",&n); /*alocao dinmica*/ v = (float*) malloc (n*sizeof(float)); if(v == NULL) { printf("Memria Insuficiente"); return 1;

Anhanguera Educacional Estrutura de Dados - Prof. Ms. Thiago Salhab Alves } /*leitura dos valores*/ for(i=0; i<n; i++) { printf("Entre com a nota %i: ",i); scanf("%f", &v[i]); } med = media(n,v); var = variancia(n,v,med); printf("Media: %.2f Variancia: %.2f \n", med, var); getche(); /*libera memria*/ free(v); return 0; } Exemplo de uso de ponteiro e da funo malloc: #include <stdio.h> #include <conio.h> #include <stdlib.h> main() { 1 2 3 4 5 6 7 8 9 10 11 12 } Na linha 3, uma varivel inteira criada e seu endereo colocado em p. A linha 4 define o valor dessa varivel como 3. A linha 5 define q com o valor dessa varivel. O comando de atribuio na linha 5 perfeitamente vlido porque uma varivel ponteiro (q) est recebendo a atribuio do valor de outro ponteiro (p). A Figura 3 item a) ilustra a situao depois da linha 5. Observe que, nesse ponto, *p e *q referem-se a mesma varivel. A linha 6, portanto, imprime o contedo dessa varivel (que 3) duas vezes. int *p, *q; int x; p = (int*) malloc(sizeof(int)); *p = 3; q = p; printf("%d %d\n", *p, *q); x = 7; *q = x; printf("%d %d\n", *p, *q); p = (int*) malloc(sizeof(int)); *p = 5; printf("%d %d\n", *p, *q); getche();

Anhanguera Educacional Estrutura de Dados - Prof. Ms. Thiago Salhab Alves A linha 7 define o valor de uma varivel de inteiro, x, com 7. A linha 8 muda o valor de *q para o valor de x. Entretanto, como p e q apontam ambos para a mesma varivel, *p e *q tm o valor 7. Isso ilustrado na Figura 2 b). A linha 9, portanto, imprime o nmero 7 duas vezes. A linha 10 cria uma nova varivel inteira e coloca seu endereo em p. Os resultados aparecem ilustrados na Figura 2 c). Agora *p refere-se varivel inteira recm-criada que ainda no recebeu um valor. q no foi alterado; portanto, o valor de *q continua 7. Observe que *p no se refere a uma nica varivel especfica. Seu valor muda em funo do valor de p. A linha 11 define o valor dessa varivel recm-criada com 5, conforme ilustrado na Figura 2 d) e a linha 12 imprime os valores 5 e 7. p q

3 a)

x 7

p q

7 b) q

x 7 c) 7

q p 5 d) Figura 3 Ilustrao do Exemplo 7

x 7

Você também pode gostar