Projeto de Algoritmos

Alocação dinâmica de memória

Esta página é um pequeno resumo sobre alocação dinâmica de memória, ou seja, alocação que ocorre durante a execução de um programa.

Malloc e free

A função  malloc  (abreviatura de memory allocation) da biblioteca padrão aloca um bloco de bytes consecutivos na memória do computador e devolve o endereço desse bloco.  Eis um exemplo bobo que recebe um caracter e imprime o caracter seguinte da tabela ISO 8859-1:

   char *ptr;
   ptr = malloc (1);
   scanf ("%c", ptr);
   printf ("%c\n", *ptr + 1); /* não confunda com *(ptr+1) */
   free (ptr);

Eis outro exemplo bobo, que calcula a soma de dois números:

   int *ptr;
   int x;
   ptr = malloc (sizeof (int));
   scanf ("%d %d", ptr, &x);
   *ptr = *ptr + x;
   printf ("%d\n", *ptr);
   free (ptr);

A expressão sizeof (int) dá o número de bytes de um int. No meu computador, esse número é 4.

A função malloc devolve um ponteiro "genérico" — ou seja, do tipo  void *  — para um bloco de bytes consecutivos. No exemplo acima, esse ponteiro é automaticamente convertido em ponteiro-para-int uma vez que a variável ptr é do tipo int *.

A função free libera a porção de memória alocada por malloc. O comando free (ptr) avisa o sistema de que o bloco de bytes apontado por ptr está livre. A próxima chamada de malloc poderá tomar posse desses bytes.

As funções  malloc  e  free  estão na biblioteca stdlib.  Portanto, diga

#include <stdlib.h>

no início de qualquer programa que use malloc e free.

A memória não é infinita

Se a memória do computador já estiver toda ocupada, malloc não consegue alocar mais espaço e devolve NULL. Convém verificar essa possibilidade antes de prosseguir:

   ptr = malloc (sizeof (int));
   if (ptr == NULL) {
      printf ("Socorro! malloc devolveu NULL!\n");
      exit (EXIT_FAILURE);
   }

A codificação freqüente e repetida desse teste é cansativa para o programador e desvia a atenção do leitor. Por isso, vamos usar a seguinte versão alternativa de malloc:

void *mallocX (unsigned int nbytes) 
{
   void *ptr;
   ptr = malloc (nbytes);
   if (ptr == NULL) {
      printf ("Socorro! malloc devolveu NULL!\n");
      exit (EXIT_FAILURE);
   }
   return ptr;
}

A função mallocX não está em nenhuma biblioteca e é desconhecida fora dessas notas de aula. Ela é apenas uma abreviatura conveniente.

Exemplo

Eis como um vetor (= array) com n elementos inteiros pode ser alocado durante a execução de um programa  (a propósito, veja observação sobre vetores e endereços em outra página):

   int *v; 
   int n, i;
   
   scanf ("%d", &n);
   v = mallocX (n * sizeof (int));
   for (i = 0; i < n; i += 1) 
      scanf ("%d", &v[i]);
   for (i = 0; i < n; i += 1) 
      printf ("%d ", v[i]);
   free (v);

Do ponto de vista conceitual (mas apenas desse ponto de vista) o comando

   v = mallocX (100 * sizeof (int));

tem o mesmo efeito que

   int v[100];

A propósito, convém lembrar que o padrão ANSI não permite escrever "int v[n]", a menos que n seja uma constante, definida por um #define.

Exercícios

  1. Escreva uma função que receba um caracter c e transforme c em uma cadeia de caracteres, ou seja, devolva uma cadeia de caracteres de comprimento 1 tendo c como único elemento.

  2. Escreva um programa que leia um número inteiro positivo n seguido de n números inteiros e imprima esses n números em ordem invertida. Por exemplo, ao receber
        5  222 333 444 555 666
    

    o seu programa deve imprimir

        666 555 444 333 222
    

    O seu programa não deve impor limitações sobre o valor de n.

 


URL of this site: www.ime.usp.br/~pf/algoritmos/
1998 | Last modified: Fri Sep 8 09:54:35 BRT 2006
Paulo Feofiloff
IME-USP