Alocação Dinâmica em C

Por: Eduardo Casavella

Alocação Estática

Na alocação estática de memória, os tipos de dados tem tamanho predefinido. Neste caso, o compilador vai alocar de forma automática o espaço de memória necessário. Sendo assim, dizemos que a alocação estática é feita em tempo de compilação. Este tipo de alocação tende a desperdiçar recursos, já que nem sempre é possível determinar previamente qual é o espaço necessário para armazenar as informações. Quando não se conhece o espaço total necessário, a tendência é o programador exagerar pois é melhor superdimensionar do que faltar espaço.
Alocação Dinâmica

Na alocação dinâmica podemos alocar espaços durante a execução de um programa, ou seja, a alocação dinâmica é feita em tempo de execução. Isto é bem interessante do ponto de vista do programador, pois permite que o espaço em memória seja alocado apenas quando necessário. Além disso, a alocação dinâmica permite aumentar ou até diminuir a quantidade de memória alocada.
sizeof

A função sizeof determina o número de bytes para um determinado tipo de dados.

É interessante notar que o número de bytes reservados pode variar de acordo com o compilador utilizado.
Exemplo:

x = sizeof(int); //retorna 4 no gcc
malloc
A função malloc aloca um espaço de memória e retorna um ponteiro do tipo void para o início do espaço de memória alocado.
free
A função free libera o espaço de memória alocado.

Exemplo: Vetor Dinâmico

Quando um programador define tipo e o número de elementos um vetor ele está utilizando alocação estática.

Uma alternativa interessante é declarar um vetor como ponteiro, a fim de utilizar alocação dinâmica. Para tanto devemos usar a função malloc. Porém, esta função necessita saber a quantidade de bytes que devem ser reservados. Para fazer esse cálculo usamos o comando sizeof.

Vejamos como implementar esses detalhes no exemplo prático abaixo:

#include <stdio.h>
#include <stdlib.h> //necessário para usar as funções malloc() e free()
#include <conio.h>

int main(void)
{
	float *v; //definindo o ponteiro v
	int i, num_componentes;
	
	printf("Informe o numero de componentes do vetor\n");
	scanf("%d", &num_componentes);
	
	/* ------------- Alocando dinamicamente o espaço necessário -------------
	
	1 - Calcular o número de bytes necessários
	primeiramente multiplicamos o número de componentes do vetor pela
	quantidade de bytes que é dada pelo comando sizeof,
	portanto temos:
	num_componentes * sizeof(float)
	
	2 - Reservar a quantidade de memória
	usamos malloc para reservar essa quantidade de memória,
	então temos:
	malloc(num_componentes * sizeof(float))
	
	3 - Converter o ponteiro para o tipo de dados desejado
	como a função malloc retorna um ponteiro do tipo void,
	precisamos converter esse ponteiro para o tipo da nossa variável, no caso float,
	por isso usamos o comando de conversão explicita:
	(float *)
	
	4 - juntando tudo e atribuindo em v temos o comando abaixo: */
	
	v = (float *) malloc(num_componentes * sizeof(float));
	
	//Armazenando os dados em um vetor
	for (i = 0; i < num_componentes; i++)
	{
		printf("\nDigite o valor para a posicao %d do vetor: ", i+1);
		scanf("%f",&v[i]);
	}
	
	// ------ Percorrendo o vetor e imprimindo os valores ----------
	printf("\n*********** Valores do vetor dinamico ************\n\n");
	
	for (i = 0;i < num_componentes; i++)
	{
		printf("%.2f\n",v[i]);
	}
	
	//liberando o espaço de memória alocado
	free(v);
	
	getch();
	return 0;
}

 

 

Tela de execução

exemplo de alocação dinâmica de memoria em C

Exemplo de execução de alocação dinâmica de memoria em C

 

Alocação Dinâmica de Matriz em C

Para o exemplo a seguir vamos fazer a leitura dos valores da matriz usando um arquivo texto, portanto será necessário criar o arquivo denominado ArqMatrizes.txt com os valores conforme a figura a seguir:

Esse arquivo é composto pelas dimensões das matrizes: 3 6, ou seja 3 linhas e 6 colunas, e também  pelos valores das duas matrizes com dimensão 3 x 6.

No código a seguir vamos alocar dinamicamente duas matrizes 3 X 6 e fazer a leitura dos valores do arquivo texto.

Em seguida vamos alocar dinamicamente uma terceira matriz que vai conter a soma dos valores das outras duas matrizes.

#include <stdio.h>
#include <stdlib.h> //necessário para usar as funções malloc() e free()
#include <stdlib.h>

int main(void)
{
	int i,j,n_linhas,n_colunas;
  
  //matrizes dinâmicas de duas dimensões portanto vamos necessitar um ponteiro para a linha
  //e outro ponteiro apontando para coluna
  
  int **matriz1,**matriz2,**matriz_soma; 
  FILE *ptrArq;
  
  //Abrindo o arquivo
  ptrArq = fopen("ArqMatrizes.txt", "r");
  
  //Verificando se a abertura do arquivo foi bem sucedida
  if (ptrArq == NULL)
  {
    printf("Erro ao abrir o arquivo!\n");
    printf("Saindo do programa...\n");
    system("pause");
    exit(1);//abortando o programa
  }
  
  // Leitura das dimensões da matriz a partir dos valores do arquivo
  fscanf(ptrArq,"%d %d",&n_linhas,&n_colunas);
  
  // Alocar a memória necessária para as matrizes  
  //----------------- Alocando a matriz1 ---------------
  
  // alocar a quantidade de linhas
  matriz1 = (int **)calloc(n_linhas,sizeof(int *)); 
  for (i = 0; i < n_linhas; i++)
  {
   // alocar a quantidade de colunas de cada linha
    matriz1[i] = (int *)calloc(n_colunas,sizeof(int));
  }
    
  //----------------- Alocando a matriz2 ---------------
  matriz2 = (int **)calloc(n_linhas,sizeof(int *));
  
  for (i = 0; i < n_linhas; i++)
  {
  	matriz2[i] = (int *)calloc(n_colunas,sizeof(int));
  }
    
   
  // ------- Ler os valores para as matrizes a partir do arquivo texto ------   
  for (i = 0; i < n_linhas; i++)
  {
  	for (j = 0; j < n_colunas; j++)
  	{
  		fscanf(ptrArq,"%d",&matriz1[i][j]);//ler um inteiro do arquivo e armazenar na matriz1
	}      
  }
    
      
  for (i = 0; i < n_linhas; i++)
  {
  	for (j = 0; j < n_colunas; j++)
  	{
  		fscanf(ptrArq,"%d",&matriz2[i][j]);//ler um inteiro do arquivo e armazenar na matriz2
	}     
  }
      
  fclose(ptrArq);//Fechar o arquivo
      
  // --------------- Mostrar as matrizes lidas ---------------------
  printf("Matrizes lidas do arquivo:\n");
  for (i = 0; i < n_linhas; i++)
  {
    for (j = 0; j < n_colunas; j++)
    {
    	printf("%2d ",matriz1[i][j]);
	}      
    
	printf("       ");  //Espaçamento entre as duas matrizes
    
    for (j = 0; j < n_colunas; j++)
    {
        printf("%2d ",matriz2[i][j]);
	}           
    printf("\n");
  }
  
  // Alocar memoria para matriz soma
  matriz_soma = (int **)calloc(n_linhas,sizeof(int *));
  
  for (i = 0; i < n_linhas; i++)
  {
  	matriz_soma[i] = (int *)calloc(n_colunas,sizeof(int));
  }
    
    
  // Calcular matriz soma
  for (i = 0; i < n_linhas; i++)
  {
  	for (j = 0; j < n_colunas; j++)
  	{
  		 matriz_soma[i][j] = matriz1[i][j] + matriz2[i][j];
	}     
  }    
      
  // Mostrar matriz soma
  printf("\nMatriz soma:\n");
  for (i = 0; i < n_linhas; i++)
  {
    for (j = 0; j < n_colunas; j++)
    {
    	 printf("%3d ",matriz_soma[i][j]);  
	}     
    printf("\n");
  }        
  
  //liberando a memória da matriz1 
  //para matrizes a liberação da memória ocorre na ordem inversa da alocação
  	for (i=0; i < n_linhas; i++)
	{
		free (matriz1[i]) ;
	}	   
	free (matriz1) ;

	//liberando a memória da matriz2 
	for (i=0; i < n_linhas; i++)
	   free (matriz2[i]) ;
	free (matriz2) ;

	//liberando a memória da matriz_soma
	for (i=0; i < n_linhas; i++)
	   free (matriz_soma[i]) ;
	free (matriz_soma);
  
  printf("\n");     
  system("pause"); 
  return 0;
}

Até a próxima!

6 respostas a Alocação Dinâmica em C