[Curso de AeED - Aula 02] - Alocação dinâmica de memória



Existem dois tipos de alocação de memória possíveis de se realizar ao se escrever um programa, são elas a alocação dinâmica e estática. A alocação do tipo estático ocorre em tempo de compilação, ou seja, no momento em que se define uma variável ou estrutura em que é necessário definir seu tipo e tamanho. Nesse tipo de alocação, ao se colocar o programa em execução, a memória necessária para utilizar as variáveis e estruturas estáticas precisa ser reservada e deve ficar disponível até o término do programa (rotina ou função).

A alocação dinâmica ocorre em tempo de execução, ou seja, as variáveis e estruturas são declaradas sem a necessidade de se deinir seu tamanho, pois nenhuma memória será reservada ao colocar o programa em execução. Durante a execução do programa, no momento em que uma variável ou parte de uma estrutura precise ser utilizada, sua memória será reservada e, no momento em que não for mais necessária, deve ser liberada. Isso é feito com o auxílio de comandos ou funções que permitem, por meio do programa, reservar e/ou liberar memória.

Nesta aula você aprenderá utilizar a alocação dinâmica de memória. Para isto serão utilizadas funções específicas da linguagem C que permitem a alocação e liberação de memória em tempo de execução.




1-    Alocação dinâmica de memória

Várias linguagens de programação possibilitam manipular dinamicamente a memória das suas estruturas de dados. Algumas linguagens como o Java possibilitam que uma estrutura de dados cresça ou diminua quase que sem interferência do programador. Outras linguagens como o C exigem que o trabalho de alocação de memória seja feito antecipadamente pelo programador.
Na linguagem C, a alocação dinâmica de memória pode ser realizada com apenas quatro chamadas a funções:

Função malloc

É a função malloc que realiza a alocação de memória. Deve-se informar para a função a quantidade de bytes para alocação. A função irá retornar, se existir memória suiciente, um endereço que deve ser colocado em uma variável do tipo ponteiro.
Como a função retorna um ponteiro para o tipo void, deve-se utilizar o typecast, transformando este endereço para o tipo de ponteiro desejado.

Função calloc

Em vez de se alocar uma quantidade de bytes através da função malloc, pode-se usar a função calloc e especiicar a quantidade de bloco de um determinado tamanho.
Funcionalmente a alocação irá ocorrer de maneira idêntica. A única diferença entre o malloc e o calloc é que a última função, além de alocar o espaço, também inicializa o mesmo com zeros.
Função realloc
Às vezes é necessário expandir uma área alocada. Para isto deve-se usar a função realloc. Deve-se passar para ela o ponteiro retornado pelo malloc e a indicação do novo tamanho. A realocação de memória pode resultar na troca de blocos na memória.

Função free

Quando não se deseja mais uma área alocada, deve-se liberá-la através da função free. Deve ser passado para a função o endereço, que se deseja liberar, que foi devolvido quando a alocação da memória ocorreu.

2-    Utilizando as funções para alocação de memória

Malloc

Um vetor nada mais é do que um ponteiro com alocação estática de memória. A declaração int aVetor[10]; é equivalente:

int *aVetor;
aVetor = (int *) malloc(10 * sizeof(int *));

Quando se quer criar estruturas com dois índices (matrizes), três índices (tijolos) etc. A declaração da matriz seria algo como int aMatriz[2][3];, utilizando ponteiros para declarar uma matriz deve-se usar:

int **aMatriz;
aMatriz = (int **) malloc( 2 * sizeof(int *));
for(i = 0 ; i < 2 ; i++){
aMatriz[i] = (int*)malloc(3 * sizeof(int));
}

A notação aMatriz[i][j] pode ser utilizada com matrizes alocadas dinamicamente equivalente a *(aMatriz[i]+j) ou *(*(aMatriz+i)+j). Ou seja, pega-se o endereço de aMatriz e encontra-se o endereço da i-ésima linha (i*sizeof(int *)) posições à frente (aMatriz[i] é equivalente a *(aMatriz+i)). Este endereço pode ser interpretado como um vetor, ao qual somam-se j*sizeof(int) posições para encontrar o elemento aMatriz[i][j].

Os trechos a seguir utilizam as funções malloc e realloc para criar e aumentar o tamanho de um vetor dinamicamente (em tempo de execução). No caso de algum erro, as funções retornam um ponteiro nulo (NULL) para indicar erro de alocação de memória.

int *p;
int i,k, n;
printf("\nDigite a quantidade de numeros que serao digitados ->"); scanf("%d", &i);

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);
}

O programa a seguir utiliza a função calloc para criar uma matriz em tempo de execução. De forma idêntica a malloc, a função calloc retorna um ponteiro nulo (NULL) no caso de erro de alocação de memória.

#include <stdio.h>
#include <stdlib.h>

int main(){

    int **p;

    int i,j;

    i = 3;
    j = 3;

    /* aloca as linhas da matriz */
    p = (int **) calloc (i, sizeof(int *));
  if (p == NULL) {
     printf ("** Erro: Memoria Insuficiente **");
     return (NULL);
     }

     int m;
  /* aloca as colunas da matriz */
    for ( m = 0; m < i; m++ ) {
      p[m] = (float*) calloc (j, sizeof(float));
      if (p[m] == NULL) {
         printf ("** Erro: Memoria Insuficiente **");
         return (NULL);
         }
    }

    p[0][0] = 10;
    p[0][1] = 20;
    p[0][2] = 30;

    int k, l;
    for(k = 0 ; k < i ; k++){
        for(l = 0 ; l < j ; l++){
            printf("|%d|",p[k][l]);
        }
    }

}


3-    Alocando registros dinamicamente

struct ST_DADOS {
char nome[40];
struct nascimento {
int ano;
int mes;
int dia;
} dt_nascimento;
};


struct ST_DADOS * p;

p = (struct ST_DADOS *) malloc(sizeof(struct ST_DADOS));



Referências

LAUREANO, Marcos; Estrutura de dados com algoritmos em C; Editora BRASPORT, São Paulo; 2008; 

[Curso de AeED - Aula 02] - Alocação dinâmica de memória [Curso de AeED - Aula 02] - Alocação dinâmica de memória Reviewed by Vinicius dos Santos on 04:29:00 Rating: 5

Nenhum comentário

Escreve ai sua opinião!