LINGUAGEM: Linguagem C - Capítulo 2 - Parte 6

Alocação Dinâmica

Definição

ALOCAÇÃO DINÂMICA é o processo através do qual um programa pode criar novas variáveis (áreas de memória) em tempo de execução.

Variáveis alocadas dinâmicamente são criadas em uma área de memória livre chamada de HEAP e são acessadas através de PONTEIROS.


Funções de Alocação Dinâmica em C

Padrão ANSI

  • #include <stdlib.h>
    • void * calloc(size_t num, size_t size);
      • Aloca uma quantidade de memória igual a num*size. Isto é, aloca memória suficiente para um ARRANJO de num VARIÁVEIS de tamanho size.
      • Devolve o endereço para o primeiro byte da região alocada. Se não houver memória suficiente para satisfazer a solicitação, é devolvido NULL (endereço nulo).
    • void * malloc(size_t size);
      • Aloca uma quantidade de memória igual a size. Isto é, aloca memória suficiente para uma VARIÁVEL de tamanho size.
      • Devolve o endereço para o primeiro byte da região alocada. Se não houver memória suficiente para satisfazer a solicitação, é devolvido NULL (endereço nulo).
    • void * realloc(void * ptr, size_t size);
      • Modifica o tamanho da memória previamente alocada apontada por ptr para um novo tamanho especificado por size. O valor size pode ser maior ou menor que o original.
      • Retorna o endereço para o primeiro byte da região de memória redimensionada. Se não houver memória suficiente no HEAP para satisfazer a solicitação, é devolvido NULL (endereço nulo) e o endereço originalmente em ptr é deixado inalterado.
    • void free(void * ptr);
      • Devolve ao HEAP a memória apontada por ptr, tornando a memória disponível para alocação futura.
      • Deve ser chamada somente com um PONTEIRO ptr cujo endereço de memória foi previamente alocado por meio de uma das funções do sistema de alocação dinâmica (calloc(), malloc(), realloc()).

Outras

  • #include <string.h>
    • char * strdup(const char * pstr);
      • Duplica a STRING apontada por pstr. Ou seja, aloca no HEAP strlen(pstr)+1 bytes e copia a STRING começando em pstr para o endereço alocado.
      • Retorna o endereço alocado contendo uma cópia da STRING apontada por pstr ou NULL caso não haja memória suficiente no HEAP.

Ex.: O trecho de código abaixo:
char   str[] = "Teste";
 char * pstr = strdup(str);
É equivalente a:
char   str[] = "Teste";
 char * pstr = calloc(strlen(str) + 1, sizeof char);
 strcpy(pstr,str);

Atividade 1

Utilizando as funções de alocação dinâmica em C, iremos agora implementar uma segunda versão do programa lista de strings estudado na aula Ponteiros.

list.h

/* list.h, Rev. 1.2
   (c) 2007, Luciano R. Coutinho <lrc@deinf.ufma.br>
   
   Implements a list of strings.
**/

#ifndef LIST_H
#define LIST_H

unsigned short list_size(void);

void    list_add(const char * str, unsigned short pos);
char *  list_rem(unsigned short pos);
void    list_set(const char * str, unsigned short pos);
char *  list_get(unsigned short pos);

void    list_print(void);

#endif

list.c

/* list.c, Rev. 1.3
   (c) 2007, Luciano R. Coutinho <lrc@deinf.ufma.br>
   
   Implements a list of strings.
**/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "list.h"
#include "xcpt.h"

/** private data */
static  char ** list;
static  unsigned short  size = 0;

static  char xcpt_cmsg[XCPT_CMSG_MAX_SIZE+1];

/** public functions */

unsigned short list_size(void) {
        return size;
}

/*
  Add a new element str in the list at a given position pos.
  From pos to the end of the list, all existing elements are
  shifted right.
  
  Throws:
         INDEX_OUT_OF_BOUNDS_XCPT  when pos is invalid ( > size +1 )
         NULL_POINTER_XCPT         when there is no memory available
       to add a new element to the list.
**/
void    list_add(const char * str, unsigned short pos) {
        char * line = strdup(str);

        sprintf(xcpt_cmsg,"%s, %d: list_ins (\"%s\",%d);",__FILE__,__LINE__,str,pos);

        if ( line == NULL ) {
             THROW(NULL_POINTER_XCPT,xcpt_cmsg);
             return ;
        }

        if ( pos > size + 1 ) {
             THROW(INDEX_OUT_OF_BOUNDS_XCPT,xcpt_cmsg);
             return ;
        }
        
        if ( size % 10 == 0 ) {
  char ** aux = (char **) realloc(list,(size + 10)*(sizeof (char**)));

         if ( aux == NULL ) {
          THROW(NULL_POINTER_XCPT,xcpt_cmsg);
               return ;
         }
  
  list = aux;
        }
                
        if ( pos == 0 ) {
             list[size] = line;
        } else {  
             int  i;

             for ( i = size ; i >= pos; i-- )
                 list[i] = list[i-1];
             
             list[i] = line;
        }
        size++;
}

char *  list_rem(unsigned short pos) {
 THROW(FUNCTION_NOT_IMPLEMENTED_XCPT,"list_rem();");
}

void    list_set(const char * str, unsigned short pos) {
 THROW(FUNCTION_NOT_IMPLEMENTED_XCPT,"list_set();");
}

char *  list_get(unsigned short pos) {
 THROW(FUNCTION_NOT_IMPLEMENTED_XCPT,"list_get();");
}

void list_print(void) {     
     int i;
     
     for ( i=0; i < size; i++ )
         printf("%2d: %s\n",i+1,list[i]);

}

Exercícios

  1. Conclua a Atividade 1 implementando as funções:
    • char * list_rem(unsigned short pos);
    • void list_set(const char * str, unsigned short pos);
    • char * list_get(unsigned short pos);
  2. Teste a nova implementação de list.h e list.c com o mesmo arquivo main.c apresentado na aula Ponteiros.
Bibliografia e fonte:

  • [CCT] Schildt, H. (1996) C, completo e total: 3a Ed.. São Paulo, Makron.
  • LP, UFMA; Coutinho, Lucian. Linguagem de programação para ciencia da computação da ufma.http://www.deinf.ufma.br/~lrc/2009.1/LP/
  • [K&R] KERNIGHAN, B. e RITCHIE, D. (1990) C, a linguagem de programação: padrão ANSI. Rio de Janeiro: Campus.
  • DEITEL, H. M. (1999) Como programar em C. Rio de Janeiro: LTC.
  • Módulo Consultoria e Informática (1989) Linguagem C: programação e aplicações. Rio de Janeiro: LTC.