A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

INE5408 Estruturas de Dados

Apresentações semelhantes


Apresentação em tema: "INE5408 Estruturas de Dados"— Transcrição da apresentação:

1 INE5408 Estruturas de Dados
Alocação Dinâmica de Memória

2 As Funções de Alocação Dinâmica de Memória em "C"
Alocação Dinâmica é um meio pelo qual o programa pode obter memória enquanto está em execução. Já visto até agora: Constantes são "codificadas" dentro do código objeto de um programa em tempo de compilação. Variáveis globais (estáticas) têm a sua alocação codificada em tempo de compilação e são alocadas logo que um programa inicia a execução. Variáveis locais em funções (ou métodos) são alocadas através da requisição de espaço na pilha (stack).

3 StackPointer Início da Pilha HeapPointer Início da Área Alocável
Topo da Memória #include <stdio.h> char *a, *b; int func_A () { int local1, local2; } void func_B () { int localA, localB; localA = func_A(); localB = func_A(); main () { a = "Essa aula é legal"; b = "Será mesmo?" func_B(); HeapPointer Início da Área Alocável a b Variáveis estáticas P r o g r a m a Código objeto "Essa aula é ... "Será mesmo.. Constantes Sistema Operacional Base da Memória

4 StackPointer Início da Pilha HeapPointer Início da Área Alocável
Topo da Memória #include <stdio.h> char *a, *b; int func_A () { int local1, local2; } void func_B () { int localA, localB; localA = func_A(); localB = func_A(); main () { a = "Essa aula é legal"; b = "Será mesmo?" func_B(); HeapPointer Início da Área Alocável a b Variáveis estáticas Código objeto "Essa aula é ... "Será mesmo.. Constantes Sistema Operacional Base da Memória

5 StackPointer Início da Pilha HeapPointer Início da Área Alocável
Topo da Memória #include <stdio.h> char *a, *b; int func_A () { int local1, local2; } void func_B () { int localA, localB; localA = func_A(); localB = func_A(); main () { a = "Essa aula é legal"; b = "Será mesmo?" func_B(); HeapPointer Início da Área Alocável a b Variáveis estáticas Código objeto "Essa aula é ... "Será mesmo.. Constantes Sistema Operacional Base da Memória

6 StackPointer Início da Pilha HeapPointer Início da Área Alocável
Topo da Memória &main-#3 localA localB #include <stdio.h> char *a, *b; int func_A () { int local1, local2; } void func_B () { int localA, localB; localA = func_A(); localB = func_A(); main () { a = "Essa aula é legal"; b = "Será mesmo?" func_B(); StackPointer Início da Pilha HeapPointer Início da Área Alocável a b Variáveis estáticas Código objeto "Essa aula é ... "Será mesmo.. Constantes Sistema Operacional Base da Memória

7 StackPointer Início da Pilha HeapPointer Início da Área Alocável
Topo da Memória &main-#3 localA localB #include <stdio.h> char *a, *b; int func_A () { int local1, local2; } void func_B () { int localA, localB; localA = func_A(); localB = func_A(); main () { a = "Essa aula é legal"; b = "Será mesmo?" func_B(); StackPointer Início da Pilha HeapPointer Início da Área Alocável a b Variáveis estáticas Código objeto "Essa aula é ... "Será mesmo.. Constantes Sistema Operacional Base da Memória

8 StackPointer Início da Pilha HeapPointer Início da Área Alocável
Topo da Memória &main-#3 localA localB #include <stdio.h> char *a, *b; int func_A () { int local1, local2; } void func_B () { int localA, localB; localA = func_A(); localB = func_A(); main () { a = "Essa aula é legal"; b = "Será mesmo?" func_B(); &func_B-#2 local1 local2 StackPointer Início da Pilha HeapPointer Início da Área Alocável a b Variáveis estáticas Código objeto "Essa aula é ... "Será mesmo.. Constantes Sistema Operacional Base da Memória

9 StackPointer Início da Pilha HeapPointer Início da Área Alocável
Topo da Memória &main-#3 localA localB #include <stdio.h> char *a, *b; int func_A () { int local1, local2; } void func_B () { int localA, localB; localA = func_A(); localB = func_A(); main () { a = "Essa aula é legal"; b = "Será mesmo?" func_B(); &func_B-#2 local1 local2 StackPointer Início da Pilha HeapPointer Início da Área Alocável a b Variáveis estáticas Código objeto "Essa aula é ... "Será mesmo.. Constantes Sistema Operacional Base da Memória

10 StackPointer Início da Pilha HeapPointer Início da Área Alocável
Topo da Memória &main-#3 localA localB #include <stdio.h> char *a, *b; int func_A () { int local1, local2; } void func_B () { int localA, localB; localA = func_A(); localB = func_A(); main () { a = "Essa aula é legal"; b = "Será mesmo?" func_B(); StackPointer Início da Pilha HeapPointer Início da Área Alocável a b Variáveis estáticas Código objeto "Essa aula é ... "Será mesmo.. Constantes Sistema Operacional Base da Memória

11 StackPointer Início da Pilha HeapPointer Início da Área Alocável
Topo da Memória &main-#3 localA localB #include <stdio.h> char *a, *b; int func_A () { int local1, local2; } void func_B () { int localA, localB; localA = func_A(); localB = func_A(); main () { a = "Essa aula é legal"; b = "Será mesmo?" func_B(); &func_B-#3 local1 local2 StackPointer Início da Pilha HeapPointer Início da Área Alocável a b Variáveis estáticas Código objeto "Essa aula é ... "Será mesmo.. Constantes Sistema Operacional Base da Memória

12 StackPointer Início da Pilha HeapPointer Início da Área Alocável
Topo da Memória &main-#3 localA localB #include <stdio.h> char *a, *b; int func_A () { int local1, local2; } void func_B () { int localA, localB; localA = func_A(); localB = func_A(); main () { a = "Essa aula é legal"; b = "Será mesmo?" func_B(); &func_B-#3 local1 local2 StackPointer Início da Pilha HeapPointer Início da Área Alocável a b Variáveis estáticas Código objeto "Essa aula é ... "Será mesmo.. Constantes Sistema Operacional Base da Memória

13 StackPointer Início da Pilha HeapPointer Início da Área Alocável
Topo da Memória &main-#3 localA localB #include <stdio.h> char *a, *b; int func_A () { int local1, local2; } void func_B () { int localA, localB; localA = func_A(); localB = func_A(); main () { a = "Essa aula é legal"; b = "Será mesmo?" func_B(); StackPointer Início da Pilha HeapPointer Início da Área Alocável a b Variáveis estáticas Código objeto "Essa aula é ... "Será mesmo.. Constantes Sistema Operacional Base da Memória

14 StackPointer Início da Pilha HeapPointer Início da Área Alocável
Topo da Memória #include <stdio.h> char *a, *b; int func_A () { int local1, local2; } void func_B () { int localA, localB; localA = func_A(); localB = func_A(); main () { a = "Essa aula é legal"; b = "Será mesmo?" func_B(); HeapPointer Início da Área Alocável a b Variáveis estáticas Código objeto "Essa aula é ... "Será mesmo.. Constantes Sistema Operacional Base da Memória

15 Alocação Dinâmica em "C" A memória alocada pelas funções de alocação dinâmica é obtida do heap. O heap é a região de memória livre que se encontra entre o programa (com a área de armazenamento permanente) e a pilha (stack). O tamanho do heap é, a princípio, desconhecido do programa. "C" possui duas funções básicas para gerência de memória: malloc(nº de bytes) - aloca memória. free(endereço) - libera memória.

16 Função malloc() Protótipo: void *malloc(size_t número_de_bytes);
Detalhes: devolve um ponteiro do tipo void (sem tipo) para o início (1º byte) da área de memória alocada; isto significa que o valor deste ponteiro pode ser atribuído a qualquer variável do tipo ponteiro. Para isto deve ser utilizado sempre um typecasting. Ex.: se x é um ponteiro para inteiro, então: x = (int *) malloc( sizeof(int) ); número_de_bytes é a quantidade de bytes alocada; se a memória for alocada no topo do heap, o heapPointer é atualizado (incrementado de número_de_bytes); o tipo size_t é definido em stdlib.h.

17 StackPointer Topo da Pilha HeapPointer Topo da Área Alocável
Topo da Memória #include <stdlib.h> #include <stdio.h> char *p; int *q; main() { // Aloca 1000 bytes de RAM. p = (char *) malloc(1000); // Aloca espaço para 50 // inteiros. q = (int *) malloc(50*sizeof(int)); } HeapPointer Topo da Área Alocável 50*int = 200 bytes 1000 bytes p q Variáveis estáticas Código objeto Constantes Sist.Operacional Base da Memória

18 StackPointer Topo da Pilha HeapPointer Topo da Área Alocável
Topo da Memória Espaço de variáveis locais alocado malloc devolve: um ponteiro para a área alocada; o ponteiro nulo (NULL) caso não seja possível alocar a memória requisitada. Convém verificar se foi possível alocar a memória. #include <stdio.h> #include <stdlib.h> char *p; main() { // Tenta alocar 1000 bytes de // RAM. p = malloc(1000); // Testa se p é igual a // NULL. if (p == NULL) printf(“%s”, "Sem memória!"); } StackPointer Topo da Pilha HeapPointer Topo da Área Alocável Já alocado antes p Variáveis estáticas Código objeto "Sem memória" Constantes Sist.Operacional Base da Memória

19 Função free() Protótipo: void free( void *p ); Detalhes:
devolve memória previamente alocada ao sistema; a memória devolvida é aquela que foi alocada com um ponteiro com o valor de p: o valor de p deve ser um valor que foi alguma vez retornado por malloc(); não é possível alocar um vetor enorme e depois desalocar a parte dele que "sobrou“; a utilização de free() com um valor de ponteiro qualquer poder ter resultados catastróficos; a gerência de buracos no heap é responsabilidade do sistema operacional.

20 Exercício: Lista com um vetor de Ponteiros para Strings
Uma lista ordenada pode conter Strings de qualquer comprimento < 10000; esta lista tem um número de elementos máximo fixo (100) e é implementada como um vetor de ponteiros para Strings; utilize as rotinas de lista com vetor que você implementou para a agenda. Um novo String é lido primeiramente para dentro de uma variável auxiliar qualquer; então é alocada memória para exatamente o seu tamanho e ele é copiado para esta área. Para copiar um String utilize strcpy(); por fim um lugar na lista é encontrado para ele. A posição escolhida do vetor de ponteiros da lista é instanciada através da atualização dos valores do ponteiro da posição do String na lista com o endereço do string.

21 Modelagem da estrutura
Strings lidos do usuário e alocados no Heap 1 S a b ã o \0 C o n s t i t u i r \0 Lista com Vetor de Ponteiros

22 Modelagem da Lista Pseudo-código:
constantes MAXLISTA = 100; tipo tLista { // Vetor de ponteiros para caracter. caracter *dados[MAXLISTA]; inteiro último; }; Importante: observe que criando uma variável do tipo tLista você não vai estar alocando memória para os strings a serem lidos, apenas para os ponteiros para eles.

23 Organização de memória para o exercício
Topo da Memória StackPointer Topo da Pilha Espaço de variáveis locais alocado Organização de memória para o exercício HeapPointer Topo da Área Alocável str4 str3 str2 str1 Var.Estáticas Vetor de char* Código objeto Constantes Sist.Operacional Base da Memória

24 Para verificar o comprimento de um String:
utilize a função strlen(); esta função devolve o comprimento (em caracteres imprimíveis) de um string. Protótipo: int strlen(char *p); #include <stdio.h> #include <stdlib.h> #include <sting.h> char p[90] = "Carro"; main() { printf("%i", strlen(p)); } Imprime: 5

25 Para copiar um String: Imprime: Carro utilize a função strcpy();
esta função copia o conteúdo de um string (dado por um apontador) para a posição de memória dada por outro apontador. Protótipo: char *strcpy(char *destino, char *fonte); #include <stdio.h> #include <stdlib.h> #include <sting.h> char p[90] = "Carro"; char lata[20]; main() { strcpy(lata, p)); printf("s%", lata); } Imprime: Carro

26 Detalhes: Lista Ordenada com um vetor de ponteiros para Strings
Como você não sabe o comprimento do String que o usuário vai digitar, use primeiro uma variável auxiliar grande (10000 posições) para guardar o que foi digitado; a lista deve ser passada como parâmetro para todas as funções que a utilizam, bem como as variáveis de controle da lista; todas as funções de lista ordenada implementadas anteriormente devem ser reimplementadas para utilizar estes Strings; para a leitura de um String utilize scanf("%s", entrada).

27 Exercício 2: Trabalho com Passagem de Parâmetros
Agora você vai fazer um programa que manipula mais de uma lista; o programa fará isto com um único conjunto de funções e passagem das diversas listas como parâmetros; como aplicação imaginemos um sistema de contabilidade simples; você vai ter um Plano de Contas constituído por duas listas: débitos e créditos; o mesmo conjunto de funções (que você já implementou) vai poder ser utilizado para isso: você somente precisa ampliar o conjunto de parâmetros da função para passar por referência também a lista que você quer alterar. A passagem de parâmetro da lista deve ser por referência porque você deseja que as alterações sejam persistentes.

28 Modelagem de um Lançamento
Cada lista de débitos ou créditos é constituída por lançamentos. Cada lançamento possui: um valor real (positivo); um nome. Por exemplo, “Pagar proteção à Mafia” Estrutura: tipo tLançamento { caracter *nome; real valor; };

29 Modelagem de um tipo Lista para Débitos ou Créditos
Pseudo-código: constantes MAXLISTA = 100; tipo tListaContábil { tLançamento dados[MAXLISTA]; inteiro último; }; Importante: observe que criando um vetor de lançamentos, você não vai estar reservando memória para os nomes destes, pois o campo nome é só um ponteiro.

30 Usando (pseudo-código)
Crie variáveis globais: tListaContábil débitos, créditos; Passe estas variáveis como parâmetros por referência: adiciona(&débitos, nomeLanc, valorLanc); Cabeçalho: Inteiro FUNÇÃO adiciona(tListaContábil *plano; caracter *nome; real valor); Importante: nome é passado como ponteiro para caracter. Use um buffer global para ler o nome do lançamento do usuário.

31 Modelagem da estrutura
Strings lidos do usuário e alocados no Heap 1 R$ 5,00 S a b ã o \0 R$ 505,00 P a s s a g e n s \0 Lista de débitos ou de créditos com Vetor de Estruturas do tipo Lançamento

32 Usando (código “C”) Referencie diferentemente se estiver usando ponteiros para a lista ou a lista diretamente: tListaContabil debitos, creditos; debitos.dados[2].valor = 5.0; strcpy(debitos.dados[2].nome, buffer); Dentro das funções: Suponha: tListaContabil *ponteiro e ponteiro = &debitos; ponteiro->dados[2].valor = 5.0; strcpy(ponteiro->dados[2].nome, buffer);

33 Headerfile: como garantir Inclusão Única
// Arquivo: pilha.h #ifndef EstruturaDaPilha #define EstruturaDaPilha // Definir uma estrutura para a pilha. struct estruturaDaPilha { int topo; int dados[MAXPILHA]; }; // Define um tipo que tem a estrutura da // pilha. typedef struct estruturaDaPilha pilha; #endif

34 Headerfiles: Importante
A diretiva de compilação #ifndef (if not defined) diz que aquela área de código fonte entre o #ifndef e o #endif somente será levada em conta pelo compilador se o argumento de #ifndef ainda não houver sido definido na mesma sessão de compilação no escopo de um módulo; isso garante que código que a gente "por via das dúvidas" inclui mais de uma vez em um módulo não seja considerado duas vezes; um exemplo de como isto é útil está na diretiva #include <stdio.h> que está presente tanto em pilha.h quanto em pilha.c e em aplic.c; como aplic.c carrega pilha.h "para dentro" de si mesmo, carregará também stdio.h. Como está explicitamente também carregando stdio.h, se não houver uma diretiva #ifndef em stdio.h, ele terá o mesmo código existente em stdio.h duas vezes.

35 Módulo: lista.h #ifndef Lista #define Lista
typedef struct estruLista { char *elemento[30]; int ultimo; int max; }; typedef struct estruLista lista; #endif

36 Módulo: lista.c #include <stdio.h> #include <stdlib.h>
#include “lista.h” lista *criaLista() { lista *nova; nova = malloc( sizeof(lista) ); nova->max = 30; nova->ultimo = -1; return (nova); } void destroiLista(lista *morta) { int i; // Libera memória ocupada pelos Strings. for (i=0; morta->ultimo; i++) free( morta->elemento[i] ); // Libera memória da lista. free( morta );

37 Exercício de Implementação 4
Implementação de um programa com número variável de filas com vetores alocadas dinamicamente usando o TAD lista com vetor. Este trabalho é bem fácil porque você já implementou praticamente tudo o que precisa. Só tem agora que modificar um pouco a forma de gerenciar os seus dados. Tome o TAD Fila com Vetor que você já implementou e crie um programa para gerenciar uma lista contendo um número variável e menor do que 20 desses TADs. Cada Fila deverá ter no máximo 20 posições. Para tanto adapte o TAD Lista com Vetor que você implementou de forma que cada elemento da lista seja um tipo ponteiro para um TAD Fila. Quando você for inserir uma nova fila, você a cria dinamicamente, alocando memória para ela e inicializando os seus campos de controle.


Carregar ppt "INE5408 Estruturas de Dados"

Apresentações semelhantes


Anúncios Google