Baixe o app para aproveitar ainda mais
Prévia do material em texto
Alocação de memória ESTRUTURA DE DADOS Objetivos de Aprendizagem Descrever o procedimento de aplicação de memória estática; Analisar diferentes procedimentos de alocação estática de memória em estruturas de dados; Projetar estruturas de dados em determinada linguagens de programação com alocação estática de memória; Objetivos de Aprendizagem Descrever o procedimento de alocação de memória dinâmica; Analisar diferentes procedimentos de alocação dinâmica de memória em estruturas de dados; Projetar estruturas de dados em determinada linguagem de programação com alocação. Agenda Mapa de memória da Linguagem C Alocação de Memória ◦ Estática x Dinâmica ◦ Sequencial x Encadeada ◦ Estática e Sequencial ◦ Estática e Encadeada ◦ Dinâmica e Sequencial ◦ Dinâmica e Encadeada Alocando memória em C. Mapa de Memória da Linguagem C Mapa Conceitual de memória Fonte: http://diegofatec.xpg.uol.com.br/dados/apostilando_c.pdf Mapa de Memória da Linguagem C Região Pilha ◦ Possui endereço de retorno das chamadas das funções; ◦ Argumentos para funções e variáveis locais; ◦ Guarda o estado atual da UCP. Mapa de Memória da Linguagem C A heap é uma região de memória livre usada pelos programadores, via funções de alocação dinâmica de C, em aplicações como listas encadeadas e árvores Região Variáveis Globais É aquela em que as variáveis globais estão armazenadas Região Código do Programa É a memória que contém o código do seu programa (Herbert Schildt) Memória Necessidade para executar um programa; Solicitação ao Sistema Operacional; Memória alocada na iniciação do programa; Memória alocada durante a sua execução. Alocação de Memória Estática vs. Dinâmica Estática ◦ Quantidade total de memória utilizada pelos dados é previamente conhecida e definida de modo imutável, no próprio código-fonte do programa ◦ Durante toda a execução do programa a quantidade de memória não varia Alocação estática Na alocação estática o espaço de memória, que as variáveis irão utilizar durante a execução do programa, é definido no processo de compilação. Não sendo possível alterar o tamanho desse espaço durante a execução do programa. Alocação estática char a; // 1 byte na memoria int vetor[10]; /* O int ocupa 4 bytes na memória, portanto 4x10=40 bytes */ double matriz[3][3]; /* O double ocupa 8 bytes na memória, portanto 3x3x8=72 bytes */ Estática vs. Dinâmica Estática ◦ Vantagem: Mantém os dados organizados na memória ◦ Desvantagem: Desperdício de memória Limitação de memória Estática vs. Dinâmica Dinâmica ◦ É capaz de criar novas variáveis enquanto executa, ou seja, em tempo de execução (run time) ◦ As práticas mais usadas desse tipo de alocação são: Alocação das variáveis locais E parâmetros passados por valor Sequencial x Encadeada Sequencial ◦ Consiste em alocar os itens nas células de memória consecutiva Sequencial x Encadeada Vantagens ◦ Fácil endereçamento Item pode ser alcançado de uma forma direta Desvantagens ◦ Manutenabilidade difícil Há dificuldades para inserir e remover itens após criação do array Sequencial x Encadeada Encadeada ◦ Os itens alocados podem ocupar qualquer endereço na memória ◦ Para preservar a forma linear é armazenado o endereço da próxima estrutura junto com cada item alocado Sequencial x Encadeada Encadeada ◦ A estrutura deve possuir pelo menos dois campos: Um com os dados do item E outro com o endereço da próxima estrutura Sequencial x Encadeada Encadeada ◦ Vantagem: Facilidade na inserção e retirada dos itens na lista ◦ Desvantagem: Menor velocidade de acesso pois precisamos partir do primeiro item da fila para seguir os campos de ligação Alocação Estática e Sequencial A forma mais natural de armazenar um conjunto de dados, com quantidade de elementos pré-determinada, consiste em colocar os elementos em células de memórias consecutivas, um após o outro Alocação Estática e Sequencial Assim, se cada célula tem um endereço único ᵋ e utiliza k bytes, temos: ◦ Endereço do elemento ai = ᵋ ◦ Endereço do elemento ai - 1 = ᵋ - k ◦ Endereço do elemento ai + 1 = ᵋ + k Alocação Estática e Sequencial Implementação ◦ Há duas formas de implementar, em C, a alocação estática e sequencial: Através das variáveis globais ou dos ponteiros ◦ O importante é que ambas as formas devem fixar o tamanho do array. Alocação Estática e Sequencial Exemplo de uma alocação estática usando variáveis globais Alocação Estática e Sequencial Exemplo de uma alocação estática usando variáveis globais Alocação Estática e Sequencial Exemplo de uma alocação estática usando ponteiros Alocação Estática e Sequencial Exemplo de uma alocação estática usando ponteiros Alocação Estática e Sequencial Exemplo de uma alocação estática usando malloc Alocação Estática e Sequencial Exemplo de uma alocação estática usando malloc Alocação Estática e Encadeada As listas estáticas são armazenadas como vetores tem seu tamanho SEMPRE fixo E as operações de inserção podem ser de dois tipos: ◦ desordenada e ordenada Alocação Estática e Encadeada Na forma estática sequencial, ordenar significa movimentar os elementos para os espaços livre na extremidade Alocação Estática e Encadeada Realizar inserções numa estrutura de dados onde os elementos podem estar fisicamente desordenados, mas estarão logicamente ordenados Alocação Estática e Encadeada Passo a Passo da inserção na lista estática e encadeada Alocação Estática e Encadeada Alocação Estática e Encadeada Alocação Estática e Encadeada Alocação Estática e Encadeada Alocação Dinâmica e Sequencial Ao se tratar de realizar uma alocação que altera a quantidade de elementos durante o tempo de execução, e ao mesmo tempo trabalha em uma memória consecutiva, ou seja, memória sequencial, estamos nos referindo aos arrays dinâmicos Alocação Dinâmica e Sequencial Alocação Dinâmica e Encadeada Esse tipo de alocação gera estruturas de dados bastantes utilizadas e com grande poder de armazenamento e manipulação: ◦ Listas encadeadas ◦ Filas ◦ Pilhas ◦ Deques ◦ Árvores ◦ Grafos Alocação Dinâmica e Encadeada A vantagem de usar esse tipo de alocação está no fato de a qualquer momento que precisarmos de espaço em memória poderemos alocar de maneira simples e rápida Alocação Dinâmica e Encadeada Características que devem ser observadas: ◦ Os dados estão espalhados no computador em vários blocos; ◦ Utiliza-se registros como estrutura de dados Esta por sua vez incluem um campo do tipo ponteiro (link), para permitir encadear os dados e indicar onde está o dado seguinte na memória (encadeando); Alocação Dinâmica e Encadeada Características que devem ser observadas: ◦ Espaços são criados conforme a necessidade em tempo de execução Permitindo criar programas que utilize apenas memórias necessárias; ◦ Podemos liberar espaço de memória quando estes não forem mais necessários pelos programas Alocação Dinâmica e Encadeada Memória Suficiente ◦ O primeiro passo a ser verificado nesse tipo de alocação, é o de memória suficiente Alocação Dinâmica e Encadeada A figura mostra uma estrutura criada com registros que são encadeados através do uso de ponteiros Estes blocos espalhados pela memória, vão resultar em estruturas denominadas de listas encadeadas Alocação de Memória Ex: Armazenando 10 elementos inteiros int *v v = (int *) malloc(10*sizeof(int)); if(v==NULL){ printf(“Memória insuficiente”); /*aborta o programa e retorna 1 para o sist. operacional*/ exit(1); } /*libera o espaço de memória alocado dinamicamente*/ free(v); Alocação de Memória Vale salientar... ◦ Vetores estáticos tendem a ser mais eficientes do que os dinâmicos, já que estes têm uma indireção a mais - primeiro acessa o valor do endereço armazenado na variável ponteiro para então acessar o elemento do vetor (CELES, W., CERQUEIRA, R., RANGEL, J.L.) Alocação de Memória Vetores Bidimensionais – matrizes float mat[4][3]; Armazenamento contínuo... float mat[4][3] = {{5.0,10.0,15.0}, {20.0,25.0,30.0}, {35.0,40.0,45.0}, {50.0,55.0,60.0}} Alocação de Memória Armazenamento contínuo... 5.0,10.0,15.0 20.0,25.0,30.0 35.0,40.0,45.0 50.0,55.0,60.0 j i 60.0 55.0 50.0 45.0 40.0 35.0 30.0 25.0 20.0 15.0 10.0 5.0 Vetor-linha Contém a mesma limitação dos vetores Alocação de Memória Matrizes Dinâmicas ◦ Para trabalhar com matrizes alocadas dinamicamente, temos que criar abstrações conceituais com vetores: 1. Matriz representada por um vetor simples 2. Matriz representada por um vetor de ponteiros Alocação de Memória Matriz representada por um vetor simples a b c d e f g h i j k l j = 2 i = 1 a b c d e f g h i j k l •Acesso ao elemento: •mat[i*n+j], onde n é o número de colunas float *mat; ... mat = (float*) malloc(m*n*sizeof(float)); Alocação de Memória Matriz representada por um vetor de ponteiros ◦ A matriz é representada por um vetor de vetores, ou vetor de ponteiros, no qual cada elemento armazena o endereço do primeiro elemento de cada linha int i; /*matriz representada por um vetor de ponteiros*/ float **mat; ... mat = (float**) malloc(m*sizeof(float*)); for(i=0; i<m; i++) mat[i] = (float*) malloc(n*sizeof(float)); Alocação de Memória Matriz representada por um vetor de ponteiros a b c d e f g h i j k l j = 2 i = 1 a b c d e f g h i j k l i = 1 j = 2 Alocando memória em C Linguagem C O padrão C ANSI define 4 funções para o sistema de alocação dinâmica, disponíveis na biblioteca stdlib.h malloc calloc realloc free Linguagem C - malloc A função malloc serve para alocar memória e tem o seguinte protótipo: void * malloc (unsigned int num); A função toma o número de bytes que queremos alocar (num), aloca na memória e retorna um ponteiro void * para o primeiro byte alocado; Linguagem C - malloc O ponteiro void * pode ser atribuído a qualquer tipo de ponteiro; Se não houver memória suficiente para alocar a memória requisitada a função malloc() retorna um ponteiro nulo Linguagem C - malloc #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]){ int *p, a=4, i; //Alocando memoria a numeros inteiros p = (int *) malloc(a*sizeof(int)); //p pode ser tratado como um vetor com a posicoes if(!p){ //se nao exite p printf("ERRO: Memória Insuficiente!!"); exit; } system("PAUSE"); return 0; } Calcula o tamanho do inteiro conforme a plaforma de HW Linguagem C - calloc A função calloc também serve para alocar memória, mas possui um protótipo um pouco diferente: void * calloc (unsigned int num, unsigned int size); A função aloca uma quantidade de memória igual a num*size, isto é, aloca memória suficiente para um vetor de num objetos de tamanho size. Ela zera toda espaço alocado. Zerar significa colocar o byte 0 em todas posições de memória alocadas. Linguagem C - calloc Retorna um ponteiro void * para o primeiro byte alocado O ponteiro void * pode ser atribuído a qualquer tipo de ponteiro Se não houver memória suficiente para alocar a memória requisitada a função calloc() retorna um ponteiro nulo calloc() é como chamar malloc() e memset() Linguagem C - calloc #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]){ int *p, a=4, i; //Alocando memoria a numeros inteiros p = (int *) calloc(a, sizeof(int)); //p pode ser tratado como um vetor com a posicoes if(!p){ //se nao exite p printf("ERRO: Memória Insuficiente!!"); exit; } system("PAUSE"); return 0; } Calcula o tamanho do inteiro conforme a plaforma de HW Linguagem C – realloc A função realloc void * realloc (void *ptr, unsigned int num); A função realloc serve para realocar memória A função modifica o tamanho da memória previamente alocada apontada por *ptr para o tamanho num O valor de num pode ser maior ou menor do que o tamanho original A memória apontada pelo ptr deve ter sido alocada por malloc ou calloc Linguagem C – realloc Um ponteiro para o bloco é devolvido porque realloc() pode precisar mover o bloco para aumentar seu tamanho ◦ Se isso ocorre, o conteúdo do bloco antigo é copiado no novo bloco e nenhuma informação é perdida Se o ponteiro for nulo, aloca num bytes e devolve um ponteiro Se num é zero, a memória apontada por ptr é liberada Se não houver memória suficiente para a alocação. ◦ Um ponteiro nulo é devolvido e o bloco original é deixado inalterado Linguagem C – realloc #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]){ int *p, a=30, i; //Alocando memoria a numeros inteiros p = (int *) malloc(a*sizeof(int)); //p pode ser tratado como um vetor com a posicoes if(!p){ //se nao exite p printf("ERRO: Memória Insuficiente!!"); exit; } ... Linguagem C – realloc for (i=0; i<a ; i++) p[i] = i*i; //O tamanho de p deve ser modificado, por algum motivo a = 100; p = realloc (p, a*sizeof(int)); for (i=0; i<a ; i++) p[i] = a*i*(i-6); system("PAUSE"); return 0; } O programa guarda o número de bytes alocados numa “tabela de alocação” interna Linguagem C – realloc Como o programa sabe a quantidade de bytes que devem ser liberados? Linguagem C – free free() ◦ Quando alocamos memória dinâmica é necessário que nós a liberemos quando ela não for mais necessária void free (void *p); ◦ Basta passar para free() o ponteiro que aponta para o início da memória alocada ... int main(int argc, char *argv[]){ int *p, a=30, i; //Alocando memoria a numeros inteiros p = (int *) malloc(a, sizeof(int)); //p pode ser tratado como um vetor com a posicoes if(!p){ //se nao exite p printf("ERRO: Memória Insuficiente!!"); exit; } ... free(p); ... return 0 } Linguagem C – free Alocação de memória ESTRUTURA DE DADOS
Compartilhar