Alocação dinâmica de memória Estruturas de dados Dinâmicas 1 Alocação dinâmica de memória ► Até agora para trabalhar com strings ou arrays era absolutamente necessário saber à partida quantos elementos eram necessários guardar (no máximo). ► Neste módulo vamos superar essa limitação. 2 Alocação dinâmica de memória #include <stdio.h> #include <stdlib.h> #include <string.h> main() { char frase[100]; char copia_da_frase[100]; //100 é o tamanho máximo da frase. printf("\nIntroduza a frase: "); gets(frase); /*fazer uma cópia da frase*/ strcpy(copia_da_frase, frase); printf("Copia: %s \n", copia_da_frase); } system("pause"); 3 Alocação dinâmica de memória ► “Problemas” do programa anterior: Se a frase inicial só ocupar 20 caracteres, a variável que vai conter a cópia da frase está a ser definida com 100 caracteres, ou seja, estamos a reservar uma quantidade de memória desnecessária. 4 Alocação dinâmica de memória ► Alocação Dinâmica de memória: As funções de alocação de memória encontramse na biblioteca stdlib.h #include<stdlib.h> Função malloc – Memory Allocation void *malloc(size_t n_Bytes) 5 void * malloc(size_t n_Bytes) void * malloc(size_t n_Bytes) ►void *- a função devolve um apontador de qualquer tipo; ►malloc – nome da função; ►size_t n_Bytes – tamanho do bloco de memória a reservar; 6 void * malloc(size_t n_Bytes) ► Como esta função devolve um apontador para qualquer tipo de dados, vamos ter de avisar o compilador qual é esse tipo de dados. … int * a; char * b; float * c; a = (int *) malloc(sizeof(int)); b = (char *) malloc(100); c = (float *) malloc(sizeof(float)); … 7 void * malloc(size_t n_Bytes) função malloc um endereço de memória (se tudo correr bem) ou NULL caso a alocação falhe, logo deve fazer sempre o seguinte teste: … ►A int * a; a = (int *) malloc(sizeof(int)); if(a==NULL) { printf(“Erro na alocação de memória”); exit(1); } … 8 void * malloc(size_t n_Bytes) ► Vamos agora programar novamente o exercício que copia uma string, mas agora de modo a poupar memória. 9 #include <stdio.h> #include <stdlib.h> #include <string.h> main() { char frase[100]; char *copia_da_frase; printf("\nIntroduza a frase: "); gets(frase); /*fazer uma cópia da frase*/ copia_da_frase=(char *)malloc(strlen(frase)+1); if(copia_da_frase==NULL) { puts("Erro na alocação de memória"); exit(1); } strcpy(copia_da_frase, frase); Porquê?? printf("Copia: %s \n", copia_da_frase); } system("pause"); 10 Alocação dinâmica de memória da função malloc existe uma outra função para alocação dinâmica de memória. ► Além função chama-se calloc e a sua sintaxe é a seguinte: ► Esta void *calloc(size_t num, size_t size) size_t é um tipo de dados inteiro sem sinal 11 void *calloc(size_t num, size_t size) void *calloc(size_t num, size_t size) A função calloc reserva um espaço na memória com num elementos, todos com o mesmo size (tamanho) e devolve o endereço de memória da zona reservada. Esta função coloca todos os bytes alocados com o valor 0 (zero). 12 void *calloc(size_t num, size_t size) … float *f; int n=10; … f = (float*) calloc(n, sizeof(float)); /* reserva de memória para um bloco de n reais */ if(f == NULL) { printf("Erro na reserva de memoria\n"); exit(1); } … 13 void *calloc(size_t num, size_t size) Uma das funcionalidades desta função é a alocação dinâmica de memória para arrays. 14 #include <stdio.h> #include <stdlib.h> main() { int n; float *f; int i; printf("Indique quantos valores pretende armazenar: "); scanf("%d", &n); f = (float*) calloc(n, sizeof(float)); if(f == NULL) { printf("Erro na reserva de memoria\n"); exit(1); } /* ler dados */ for( i = 0 ; i < n ; i++) { printf("\nValor: "); scanf("%f", &f[i]); } /* mostrar dados */ for( i = 0 ; i < n ; i++) { printf("%.2f\n", f[i]); } } system("pause"); 15 Libertação de memória ► Função free() void free (void * ptr) ► ► Esta função tem a capacidade de libertar a memória reservada pelas funções anteriormente abordadas. Logo que possível devemos libertar a memória para que esta possa ser utilizável para armazenamento de outros dados. 16 #include <stdio.h> #include <stdlib.h> main() { int n; float *f; int i; printf("Indique quantos valores pretende armazenar: "); scanf("%d", &n); } f = (float*) calloc(n, sizeof(float)); if(f == NULL) { printf("Erro na reserva de memoria\n"); exit(1); } /* ler dados */ for( i = 0 ; i < n ; i++) { printf("\nValor: "); scanf("%f", &f[i]); } /* mostrar dados */ for( i = 0 ; i < n ; i++) { printf("%.2f\n", f[i]); } free(f); /* libertação da memória */ system("pause"); 17 Alteração do tamanho reservado ►A função realloc Esta função permite alterar o número de Bytes que estão associados a um Bloco (espaço de memória) anteriormente criado com a função malloc ou calloc. Sintaxe: void *realloc(void *ptr, size_t new_size) 18 #include <stdio.h> #include <stdlib.h> #include <string.h> main() { char * nome; nome=(char *) malloc(6); if(nome == NULL) { printf("Erro na reserva de memoria\n"); exit(1); } strcpy(nome, "Teste"); printf("\n%s", nome); nome=(char *) realloc(nome, 100); if(nome == NULL) { printf("Erro na reserva de memoria\n"); exit(1); } strcpy(nome, "Teste em linguagem C"); printf("\n%s \n", nome); free(nome); system("pause"); 19