Buscar

ED_I_Un3_Aloc_v4

Prévia do material em texto

Ciência da Computação 
Tecnologia em Análise e Desenvolvimento de 
Sistemas 
Estrutura de Dados I 
INF1014 - CCB1044 
Alocação Dinâmica de Memória 
SUMÁRIO 
• Conceito de Alocação Dinâmica 
• Alocação Dinâmica x Alocação Estática 
• Funções para Alocação de Memória 
• Vetores Alocados Dinamicamente 
• Matrizes Alocadas Dinamicamente 
• Estruturas Alocadas Dinamicamente 
 
 
 
Alocação Dinâmica de Memória 
• Conceito de Alocação Dinâmica 
– é o processo pelo qual um programa pode solicitar e utilizar um bloco 
de memória de tamanho arbitrário, durante sua execução. 
– é utilizada para que um programa em C utilize apenas a memória 
necessária para sua execução, sem desperdícios de memória. 
• um exemplo de desperdício de memória é quando um vetor de 1000 
posições é declarado quando não se sabe, de fato, se as 1000 posições 
serão necessárias 
– a alocação dinâmica de memória deve ser utilizada quando não se 
sabe quanto espaço de memória será necessário para o 
armazenamento de algum ou alguns valores. 
– existem funções em C próprias para fazer o "pedido" de memória. 
– um pedido de alocação será recusado se a memória estiver cheia. 
Alocação Dinâmica de Memória 
• Alocação Dinâmica x Alocação Estática 
– alocação estática 
• usa variáveis locais e globais, simples ou em forma 
de arranjo 
• exige que o programador saiba, de antemão, o 
espaço necessário 
• variáveis globais ou locais estáticas ocupam um 
espaço fixo durante toda a execução do programa 
• variáveis locais ocupam espaço na pilha, cujo 
tamanho varia conforme a necessidade (funções 
recursivas demandam mais memória de pilha) 
– alocação dinâmica 
• o espaço é ocupado no heap, que também varia 
conforme a necessidade 
 
memória do sistema 
variáveis globais 
programa 
memória livre 
(heap) 
pilha 
em casos extremos a pilha pode colidir com 
o heap e ocorrerá uma falha 
Alocação Dinâmica de Memória 
• Alocação Dinâmica x Alocação Estática 
– alocação estática 
• uso de variáveis globais (ou estáticas): 
– espaço reservado existe enquanto o programa estiver sendo 
executado 
• uso de variáveis locais: 
– espaço existe apenas enquanto a função que declarou a variável 
está sendo executada 
– liberado para outros usos quando a execução da função termina 
– alocação dinâmica 
• espaço de memória é requisitado em tempo de execução e permanece 
reservado até que seja explicitamente liberado 
• depois de liberado, espaço estará disponibilizado para outros usos e não 
pode mais ser acessado 
• espaço alocado e não liberado explicitamente, será automaticamente 
liberado ao final da execução 
Alocação Dinâmica de Memória 
• Funções para Alocação de Memória 
– Função malloc (stdio.h) 
• função para solicitar a alocação de um dado número de bytes 
 
 
• retorna um ponteiro genérico para o endereço inicial da área de memória 
alocada, se houver espaço livre: 
– ponteiro genérico é representado por void* 
– ponteiro é convertido automaticamente para o tipo apropriado 
– ponteiro pode ser convertido explicitamente 
• retorna um endereço nulo, se não houver espaço livre: 
– representado pelo símbolo NULL 
número_de_bytes: número de bytes que se quer alocar 
(o tipo size_t é um inteiro sem sinal definido em stdio.h) 
void* malloc(size_t número_de_bytes) 
como o heap não é infinito, após a alocação é necessário testar o 
valor devolvido por malloc() 
(ex_14) 
(ex_15) 
Alocação Dinâmica de Memória 
• Funções para Alocação de Memória 
– Função malloc (stdio.h) 
• Exemplos (serão vistos em detalhe mais adiante) 
– vetor de 10 inteiros 
 
 
 
 
– matriz bidimensional de inteiros 
 
 
 
 
 
 
// equivalente a int aVetor[10] 
int *aVetor; 
aVetor = (int *) malloc(10 * sizeof(int)); 
 
if (aVetor == NULL) 
 printf (“Memória insuficiente”); 
 
// equivalente a int aMatriz[2][3] 
int **amatriz; 
aMatriz = (int**) malloc(2 * sizeof(int*)); //linhas 
for( i=0; i<2 ; i++ ) 
{ 
aMatriz[i] = (int*) malloc(3 * sizeof(int)); //colunas 
} 
Alocação Dinâmica de Memória 
• Funções para Alocação de Memória 
– Função free (stdio.h) 
• função que libera bloco de memória alocado previamente 
 
 
 
• quando não se deseja mais uma área alocada, deve-se liberá-la através 
da função free. 
 
void free(void *nome) 
nome: nome do ponteiro para a memória alocada por malloc() 
é importante nunca usar free() com um argumento inválido, pois, 
isso destruiria a lista de memória livre 
(ex_16) 
Alocação Dinâmica de Memória 
• Funções para Alocação de Memória 
– Função calloc (stdio.h) 
• função para solicitar a alocação de uma dada quantidade de objetos de 
um determinado tamanho 
 
 
 
 
 
 
 
void* calloc (size_t quantidade, size_t tamanho) 
a única diferença entre malloc e calloc é que a última função, além de 
alocar o espaço, também inicializa o mesmo com zeros 
(ex_17) 
quantidade : quantidade de objetos que se quer alocar 
tamanho : número de bytes do objeto que se quer alocar 
Alocação Dinâmica de Memória 
• Funções para Alocação de Memória 
– Função realloc (stdio.h) 
• função que permite que uma área previamente alocada seja aumentada 
ou diminuída 
 
 
 
• o conteúdo do objeto será mantido até um tamanho igual ao menor dos 
dois tamanhos, novo e antigo 
• se o novo tamanho requerer movimento, o espaço reservado 
anteriormente será liberado 
• se o novo tamanho for maior, o conteúdo da porção de memória 
reservada a mais ficará com um valor sem especificação 
• se o tamanho número_de_bytes for igual a 0 e nome não for um 
ponteiro nulo, o objeto previamente reservado será liberado. 
 
void* realloc(void *nome, size_t número_de_bytes) 
(ex_18) 
nome: nome do ponteiro para a área de memória alocada que se quer reajustar 
número_de_bytes: novo número de bytes que se quer que a dada área ocupe 
Alocação Dinâmica de Memória 
• Vetores Alocados Dinamicamente 
– vetores de tamanho dinâmico, determinado em tempo de execução 
#include <stdio.h> 
#include <stdlib.h> 
int main(void) 
{ 
int *p; 
int i,k, n; 
printf("\nDigite a quantidade de números que serão digitados ->"); 
scanf("%d", &i); 
p = (int *)(malloc(i*sizeof(int))); 
if (p == NULL ){ 
printf("\nErro de alocacao de memoria"); 
exit(1); 
} 
for(k=0; k<i; k++){ 
printf("Digite o numero para o indice %d ->", k); 
scanf("%d", &p[k]); 
} 
for(k=0;k<i;k++){ 
printf("O numero do indice %d eh %d\n", k, p[k]); 
} 
 
//continua 
A função malloc reserva 
espaço suficiente para um 
vetor de inteiros. Por ex., 
para 5 elementos, serão 
reservados 20 bytes, 
considerando que cada 
inteiro ocupa 4 bytes na 
memória. 
Alocação Dinâmica de Memória 
• Vetores Alocados Dinamicamente 
– vetores de tamanho dinâmico, determinado em tempo de execução 
printf("\nDigite quantos elementos quer adicionar ao vetor ->"); 
scanf("%d", &n) 
p = (int *)(realloc(p,(i+n)*sizeof(int))); 
if( p == NULL ){ 
printf("\nErro de re-alocacao de memoria"); 
exit(1); 
} 
for(;k<(n+i);k++){ 
printf("Digite o numero para o indice %d ->", k); 
scanf("%d", &p[k]); 
} 
for( k=0;k<(i+n);k++) 
{ 
printf("O numero do indice %d eh %d\n", k, p[k]); 
} 
free(p); 
return 0; 
} 
 
A função realloc aumenta ou 
diminui o tamanho do vetor 
dinamicamente. Ela recebe o 
ponteiro para o vetor 
anterior e retorna o novo 
espaço alocado. 
Alocação Dinâmica de Memória 
• Vetores Alocados Dinamicamente 
– o uso de vetores locais a funções requer cuidado 
– exemplo 
• produto vetorial de dois vetoresu e v em 3D, representados pelas três 
componentes x, y, e z 
– variável p declarada localmente: 
» área de memória que a variável p ocupa deixa de ser válida 
quando a função prod_vetorial termina 
» função que chama prod_vetorial não pode acessar a área 
apontada pelo valor retornado 
float* prod_vetorial (float* u, float* v) 
{ 
float p[3]; 
p[0] = u[1]*v[2] – v[1]*u[2]; 
p[1] = u[2]*v[0] – v[2]*u[0]; 
p[2] = u[0]*v[1] – v[0]*u[1]; 
return p; 
} 
Alocação Dinâmica de Memória 
• Vetores Alocados Dinamicamente 
– exemplo (continuação) 
• produto vetorial de dois vetores u e v em 3D 
– variável p alocada dinamicamente 
» área de memória que a variável p ocupa permanece válida mesmo 
após o término da função prod_vetorial 
» função que chama prod_vetorial pode acessar o ponteiro 
retornado 
» problema - alocação dinâmica para cada chamada da função: 
• ineficiente do ponto de vista computacional 
• requer que a função que chama seja responsável pela liberação do 
espaço 
float* prod_vetorial (float* u, float* v) 
{ 
float *p = (float*) malloc(3*sizeof(float)); 
p[0] = u[1]*v[2] – v[1]*u[2]; 
p[1] = u[2]*v[0] – v[2]*u[0]; 
p[2] = u[0]*v[1] – v[0]*u[1]; 
return p; 
} 
Alocação Dinâmica de Memória 
• Vetores Alocados Dinamicamente 
– exemplo (continuação) 
• produto vetorial de dois vetores u e v em 3D 
– espaço de memória para o resultado passado pela função que 
chama: 
– função prod_vetorial recebe três vetores, 
» dois vetores com dados de entrada 
» um vetor para armazenar o resultado 
– solução mais adequada pois não envolve alocação dinâmica 
void prod_vetorial (float* u, float* v, float* p) 
{ 
p[0] = u[1]*v[2] – v[1]*u[2]; 
p[1] = u[2]*v[0] – v[2]*u[0]; 
p[2] = u[0]*v[1] – v[0]*u[1]; 
} 
Alocação Dinâmica de Memória 
• Matrizes Alocadas Dinamicamente 
– A alocação dinâmica para matrizes pode ser realizada de duas formas: 
• utilizando um vetor de ponteiros , mantendo alocação estática em uma 
dimensão; 
• ou utilizando ponteiro para ponteiro. 
 
linha[0] 
linha[1] 
linha[LINHAS] 
linha 
int *linha[LINHAS]; 
 linha[i] = malloc(2*(i+1)* sizeof(int)); 
linha[0][1] 
linha[0][0] 
linha[1][0] 
linha[1][3] 
*(matriz+0) 
*(matriz+1) 
*(matriz+n) 
matriz 
int **matriz; 
 matriz = (int**)malloc(lin*sizeof(int*)); 
*(*(matriz+0)+1) 
*(*(matriz+0)+0) 
*(*(matriz+1)+1) 
*(*(matriz+1)+0) 
*(matriz+i) = (int*)malloc(col*sizeof(int)); 
Linhas de tamanhos diferentes. 
Alocação Dinâmica de Memória 
• Matrizes Alocadas Dinamicamente 
– Exemplo 1 - utiliza um vetor de ponteiros (correspondendo ao 
primeiro índice da matriz), sendo que cada ponteiro aponta para o 
início de uma linha da matriz. 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#define LINHAS 10 
#define MAXCOLUNAS 60 
int main (void) { 
char *linha[LINHAS]; char temp[MAXCOLUNAS]; 
int i; 
 
for (i = 0; i < LINHAS ; i++) { 
printf ("Entre com a linha %d.\n", i); 
gets (temp); 
if (!(linha[i] = (char *)malloc((strlen(temp)+1) * sizeof(char )))) { 
printf("Sem memoria para vetor %d.\n", i); 
return 1; 
} 
strcpy (linha[i], temp); 
} 
for (i = 0; i < LINHAS ; i++) { 
printf ("Linha %d %s.\n", i, linha[i]); 
} 
return 0; 
} 
Alocação Dinâmica de Memória 
• Matrizes Alocadas Dinamicamente 
– Exemplo 2 - utiliza ponteiro para ponteiro. 
#include <stdio.h> 
#include <stdlib.h> 
int main (void) { 
int ** matriz; //ponteiro para os ponteiros 
int lin , col; //num. de linhas e colunas 
int lin1, lin2; //linhas que serão trocadas 
char linha [80]; //linha de dados 
int i, j; int *temp; 
puts("Qual o numero de linhas?"); 
gets(linha); lin = atoi(linha); 
matriz = (int **)malloc (lin*sizeof(int*)); 
if (!matriz ) { 
puts ("Nao ha memoria para alocar"); 
return 1; 
} 
puts ("Qual o numero de colunas?"); 
gets (linha); col = atoi(linha); 
for (i=0; i<lin; i++) { 
*(matriz +i) = (int*)malloc(col*sizeof(int)); 
if (!*(matriz +i)) { 
printf("Sem espaco p/ a linha %d", i); 
return 1; 
} 
} 
puts ("Entre com os dados"); 
for (i=0; i<lin; i++) { 
printf (“Entre com a linha %d\n", i); 
for (j=0; j< col; j++) { 
printf("Elemento %d %d\n", i, j); 
scanf("%d", *(matriz +i) +j); 
} 
} 
gets(linha); //só para limpar buffer 
puts("Qual a 1a linha a ser trocada ?"); 
gets(linha); lin1 = atoi(linha); 
puts("Qual a 2a linha a ser trocada ?"); 
gets(linha); lin2 = atoi(linha); 
temp = *(matriz + lin1); 
*(matriz + lin1) = *( matriz + lin2 ); 
*(matriz + lin2 ) = temp ; 
puts ("Dados trocados ."); 
for (i=0; i<lin; i++) { 
for (j=0; j< col; j++) { 
printf("%7d ", *(*(matriz +i) +j)); 
} 
return 0; 
} 
 
Alocação Dinâmica de Memória 
• Estruturas Alocadas Dinamicamente 
– estruturas também podem ser alocadas dinamicamente. 
#include <stdio.h> 
#include <stdlib.h> 
struct ST_DADOS 
{ 
char nome[40]; 
float salario; 
// estrutura dentro de uma estrutura 
struct nascimento 
{ 
int ano; 
int mes; 
int dia; 
} dt_nascimento; 
}; 
 
int main(void) 
{ 
//ponteiro para a estrutura 
struct ST_DADOS *p; 
p = (struct ST_DADOS *)malloc(sizeof(struct 
ST_DADOS)); 
 
// p->nome é um ponteiro, não precisa do & 
printf("\nEntre com o nome ->"); 
scanf("%s", p->nome); 
printf("Entre com o salario ->"); 
scanf("%f", &p->salario); 
 
printf("Entre com o nascimento ->"); 
scanf("%d%d%d", &p->dt_nascimento.dia, 
&p->dt_nascimento.mes, 
&p->dt_nascimento.ano); 
printf("\n===== Dados digitados ===="); 
printf("\nNome = %s", p->nome); 
printf("\nSalario = %f", p->salario); 
printf("\nNascimento = %d/%d/%d\n", 
p->dt_nascimento.dia, 
p->dt_nascimento.mes, 
p->dt_nascimento.ano); 
free(p); 
return 0; 
}

Continue navegando