Escolar Documentos
Profissional Documentos
Cultura Documentos
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
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
x 7