Estruturas de Dados - T.332
Capítulo 3
Parte 2:
Alocação Dinâmica de Memória
Transparência 1
3.1 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:
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).
 Constantes
Transparência 2

Programa:
#include <stdio.h>
char *a, *b;
Topo da Memória
HeapPointer
Início da Área
Alocável
Variáveis estáticas
Código objeto
Constantes
a
b
10010101...
"Essa aula é ...
"Será mesmo..
Programa
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
Inicio da Pilha
Sist.Operacional
Base da Memória
Transparência 3

Programa:
#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
Inicio da Pilha
Topo da Memória
HeapPointer
Início da Área
Alocável
Variáveis estáticas
Código objeto
Constantes
a
b
10010101...
"Essa aula é ...
"Será mesmo..
Sist.Operacional
Base da Memória
Transparência 4

Programa:
#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
Topo da Pilha
Topo da Memória
HeapPointer
Topo da Área
Alocável
Variáveis estáticas
Código objeto
Constantes
a
b
10010101...
"Essa aula é ...
"Será mesmo..
Sist.Operacional
Base da Memória
Transparência 5

Programa:
#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();
}
Topo da Memória
StackPointer
Topo da Pilha
&main-#3
localA
localB
HeapPointer
Topo da Área
Alocável
Variáveis estáticas
Código objeto
Constantes
a
b
10010101...
"Essa aula é ...
"Será mesmo..
Sist.Operacional
Base da Memória
Transparência 6

Programa:
#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();
}
Topo da Memória
StackPointer
Topo da Pilha
&main-#3
localA
localB
HeapPointer
Topo da Área
Alocável
Variáveis estáticas
Código objeto
Constantes
a
b
10010101...
"Essa aula é ...
"Será mesmo..
Sist.Operacional
Base da Memória
Transparência 7

Programa:
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();
}
StackPointer
Topo da Pilha
&main-#3
localA
localB
&func_B-#2
local1
local2
HeapPointer
Topo da Área
Alocável
Variáveis estáticas
Código objeto
Constantes
a
b
10010101...
"Essa aula é ...
"Será mesmo..
Sist.Operacional
Base da Memória
Transparência 8

Programa:
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();
}
StackPointer
Topo da Pilha
&main-#3
localA
localB
&func_B-#2
local1
local2
HeapPointer
Topo da Área
Alocável
Variáveis estáticas
Código objeto
Constantes
a
b
10010101...
"Essa aula é ...
"Será mesmo..
Sist.Operacional
Base da Memória
Transparência 9

Programa:
#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();
}
Topo da Memória
StackPointer
Topo da Pilha
&main-#3
localA
localB
HeapPointer
Topo da Área
Alocável
Variáveis estáticas
Código objeto
Constantes
a
b
10010101...
"Essa aula é ...
"Será mesmo..
Sist.Operacional
Base da Memória
Transparência 10

Programa:
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();
}
StackPointer
Topo da Pilha
&main-#3
localA
localB
&func_B-#3
local1
local2
HeapPointer
Topo da Área
Alocável
Variáveis estáticas
Código objeto
Constantes
a
b
10010101...
"Essa aula é ...
"Será mesmo..
Sist.Operacional
Base da Memória
Transparência 11

Programa:
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();
}
StackPointer
Topo da Pilha
&main-#3
localA
localB
&func_B-#2
local1
local2
HeapPointer
Topo da Área
Alocável
Variáveis estáticas
Código objeto
Constantes
a
b
10010101...
"Essa aula é ...
"Será mesmo..
Sist.Operacional
Base da Memória
Transparência 12

Programa:
#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();
}
Topo da Memória
StackPointer
Topo da Pilha
&main-#3
localA
localB
HeapPointer
Topo da Área
Alocável
Variáveis estáticas
Código objeto
Constantes
a
b
10010101...
"Essa aula é ...
"Será mesmo..
Sist.Operacional
Base da Memória
Transparência 13

Programa:
#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
Topo da Pilha
Topo da Memória
HeapPointer
Topo da Área
Alocável
Variáveis estáticas
Código objeto
Constantes
a
b
10010101...
"Essa aula é ...
"Será mesmo..
Sist.Operacional
Base da Memória
Transparência 14
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
Transparência 15
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 é ponteiro para inteiro então explicitar isto com
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.
Transparência 16

Exemplo:
StackPointer
Topo da Pilha
Topo da Memória
#include <stdlib.h>
#include <stdio.h>
char
int
*p;
*q;
main ()
{
p = (char *) malloc(1000);
// Aloca 1000
// bytes de RAM
q = (int *) malloc(50*sizeof(int));
// Aloca espaço
// para 50 inteiros.
}
HeapPointer
Topo da Área
Alocável
50*int = 200 bytes
1000 bytes
Variáveis estáticas
Código objeto
p
q
10010101...
Constantes
Sist.Operacional
Base da Memória
Transparência 17

malloc devolve:



Topo da Memória
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 ()
{ ................
p = malloc(1000)
// Tenta alocar 1000
// bytes de RAM
if (p == NULL)
// Testa se p
// diferente de 0
printf("Sem memória.");
}
Espaço de variáveis
locais alocado
StackPointer
Topo da Pilha
HeapPointer
Topo da Área
Alocável
Já alocado antes
p
Variáveis estáticas
Código objeto
10010101...
Constantes
"Sem memória"
Sist.Operacional
Base da Memória
Transparência 18
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.
valor de p deve ser um valor que foi alguma vez retornado por
malloc().
 Não é possível alocar-se um vetor enorme e depois dealocar-se a
parte dele que "sobrou".
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.
 A utilização
Transparência 19
Exercício:
Lista com um vetor de Ponteiros para Strings.



Uma lista ordenada pode conter Strings de qualquer
comprimento < 10000.
Esta lista tem 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ê utilizou 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.
Transparência 20
Modelagem da estrutura
Strings lidos
do usuário
e alocados
no Heap
-1
4
3
2
1
0
S a b ã o \0
C o n s t i t u i r \0
Lista com
Vetor de
Ponteiros
Transparência 21
Modelagem da Lista

Pseudo-código:
constantes Maxlista = 100;
tipo Lista {
caracter
inteiro
};

*dados[Maxlista];
“ Vetor de ponteiros para char “
ultimo;
Importante: Observe que criando uma variável do tipo
Lista você não vai estar alocando memória para os strings
a serem lidos, apenas para os ponteiros para eles.
Transparência 22
Topo da Memória

Organização de
memória do
Exercício:
StackPointer
Topo da Pilha
Espaço de variáveis
locais alocado
HeapPointer
Topo da Área
Alocável
str4
str3
str2
str1
Var.Estáticas
Código objeto
10010101...
Constantes
Sist.Operacional
Base da Memória
Transparência 23

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.
Transparência 24

Para copiar um String:



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, *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.
Transparência 25
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.
Da mesma maneira 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)
onde char entrada[10000].
Transparência 26
Exercício Nº 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.
Transparência 27
Modelagem de um Lancamento

Cada lista de débitos ou créditos é constituida de
um lançamento. O lançamento possui:
 Um
valor real (positivo).
 Um nome, por exemplo “pagar proteção à Mafia”

Estrutura:
tipo Lancamento {
caracter
real
};
*nome;
“ponteiro para char alocado no heap“
valor;
Transparência 28
Modelagem de um tipo Lista para
Débitos ou Créditos

Pseudo-código:
constantes Maxlista = 100;
tipo ListaContabil {
Lancamento
dados[Maxlista];
“ Vetor de Estrutura Lançamento “
inteiro
ultimo;
};

Importante: Observe que criando um vetro de lancamentos, você não
vai estar reservando memória para os nomes destes, pois o campo
nome é só ponteiros. Lembre-se de alocar.
Transparência 29
Usando (pseudo código)

Crie variáveis globais:
ListaContabil

debitos, creditos;
Passe estas variáveis como parâmetro por
referência:
adiciona(&debitos, nomeLanc, valorLanc)

Cabeçalho:
Inteiro FUNÇÃO adiciona(ListaContabil *plano;
caracter
*nome;
real
valor)

Importante: nome é passado como ponteiro para caracter.
Use um buffer global para ler o nome do lancamento do
usuário.
Transparência 30
Strings lidos
do usuário
e alocados
no Heap
Desenho
R$ 5,00
-1
4
3
2
1
0
S a b ã o \0
R$ 505,00
P a s s a g e n s \0
Lista de debitos ou
de créditos com Vetor
de Estruturas do tipo
Lançamento
Transparência 31
Usando (código C)

Referencie diferentemente se estiver usando ponteiros
para a lista ou a lista diretamente:
ListaContabil debitos, creditos;
debitos.dados[2].valor = 5.0;
strcpy(debitos.dados[2].nome, buffer);
Dentro das funções:
Suponha: ListaContabil
*ponteiro
e ponteiro = &debitos;
ponteiro->dados[2].valor = 5.0;
strcpy(ponteiro->dados[2].nome, buffer);
Transparência 32
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];
};
/* Def. um tipo que tem a estrutura da pilha. */
typedef struct estruturaDaPilha pilha;
#endif
Transparência 33
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 duvidas"
inclui mais de uma vez em um modulo não seja considerado
duas vezes.
Um exemplo de como isto e útil esta na diretiva #include
<stdio.h> que esta presente tanto em pilha.h como em pilha.c
como em aplic.c.
Como aplic.c carrega pilha.h "para dentro" de si mesmo,
carregara 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.
Transparência 34
Projetos de Implementação: Usando Make

Make: Utilitário que auxilia a compilação
de projetos formados por vários arquivos
de programas

Realiza checagem de dependências entre o
arquivo destino e os fontes

Baseia-se nas datas de arquivos
Transparência 35
Projetos de Implementação: Sintaxe do Makefile
aplic: aplic.o pilha.o
gcc -g -o aplic aplic.o pilha.o
aplic.o: aplic.c pilha.h
gcc -g - c aplic.c
pilha.o: pilha.c pilha.h
gcc -g -c pilha.c
meta: dependencia1 dependênciaN
<tab>um comando para atingir meta
<tab>outro comando para atingir meta
Transparência 36
Projetos de Implementação: Usando o Makefile

Chamada:
make -f <nome do Makefile>
 Se
o nome não for dado, make procurará por arquivos
chamados Makefile e makefile, nesta ordem.

Para definir qual meta será a primeira a ser
considerada:
 Se
você não diz nada, a primeira meta será
considerada.
 Voce pode passar como último parâmetro o nome da
meta:
make -f meuMakefile compilar

Todas as dependencias de compilar, se esta meta existir,
serão também levadas em consideração.
Transparência 37

Módulo lista.h:
#ifndef Lista
#define Lista
typedef
char
int
int
};
struct estruLista {
*elemento[30];
ultimo;
max;
typedef struct estruLista lista;
#endif

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)
{
// Libera memória p/os strings
for (i=0; morta->ultimo; i++)
free (morta->elemento[i]);
// Libera memória da lista
free ( morta );
}
Transparência 38
Download

PowerPoint97