Alocação Estática e Dinâmica Prof. M.Sc. Mariella Berger http://www.inf.ufes.br/~mberger [email protected] [email protected] Alocação Estática Estratégia de alocação de memória na qual toda a memória que um tipo de dados pode vir a necessitar é alocada de uma só vez sem considerar a quantidade que seria realmente necessária na execução do programa. Alocação Estática int v[1000] – Espaço contíguo na memória para 1000 valores inteiros – Se cada int ocupa 4 bytes, 4000bytes, ~4KB char v[50] – Espaço contíguo na memória para 50 valores char – Se cada char ocupa 1 byte, 50 bytes Alocação Estática x Dinâmica • Exemplo: Alocar nome e sobrenome dos alunos do curso – – – – – – 4000 espaços de memória Vetor de string (alocação estática) 100 caracteres (tamanho máximo do nome) Podemos então definir 40 pessoas Não é ideal pois a maioria dos nomes não usa 100 caracteres Na alocação dinâmica, não é necessário definir de antemão o tamanho máximo para os nomes Alocação Dinâmica • • • Técnica que aloca a memória sob demanda Os endereços podem ser alocados, liberados e realocados para diferentes propósitos, durante a execução do programa Espaço permanece reservado até que seja explicitamente liberado Uso da Memória • • memória estática: – código do programa – variáveis globais – variáveis estáticas memória dinâmica: – variáveis alocadas dinamicamente – memória livre – variáveis locais s Uso da Memória • • Alocação dinâmica de memória – usa a memória livre – se o espaço de memória livre for menor que o espaço requisitado, a alocação não é feita e o programa pode prever tratamento de erro Pilha de Execução – utilizada para alocar memória quando ocorre chamada de função: • • – sistema reserva o espaço para as variáveis locais da função quando a função termina, espaço é liberado (desempilhado) se a pilha tentar crescer mais do que o espaço disponível existente, programa é abortado com erro Alocação Dinâmica em C Funções disponíveis na stdlib: • Malloc – • Calloc – • void *realloc (void *ptr, unsigned int num); Free – • void *calloc (unsigned int num, unsigned int size); Realloc – • void *malloc (unsigned int num); void free (void *ptr); Sizeof – Retorna o número de bytes ocupados por um tipo Exemplo Alocação dinâmica de um vetor de inteiros com 10 elementos malloc retorna o endereço da área alocada para armazenar valores inteiros (retorna um ponteiro genérico) Retorna NULL se não for possível alocar Usar type casting para especificar um tipo int *p; p = (int *)malloc(10*sizeof(int)); Exemplo Tratamento de Erro - malloc Imprime mensagem de erro Aborta o programa (exit) Exemplo Exemplo Alocação Estática X Dinâmica Alocação estática de vetor: é necessário saber de antemão a dimensão máxima do vetor variável que representa o vetor armazena o endereço ocupado pelo primeiro elemento do vetor vetor declarado dentro do corpo de uma função não pode ser usado fora do corpo da função #define N 10 int v[10] Alocação Estática X Dinâmica Alocação dinâmica de vetor: dimensão do vetor pode ser definida em tempo de execução variável do tipo ponteiro recebe o valor do endereço do primeiro elemento do vetor área de memória ocupada pelo vetor permanece válida até que seja explicitamente liberada (através da função free) vetor alocado dentro do corpo de uma função pode ser usado fora do corpo da função, enquanto estiver alocado int *v; ‾ v = (int*)malloc(N * sizeof(int)); Função realloc Permite realocar um vetor preservando o conteúdo dos elementos, que permanecem válidos após a realocação Exemplo: m representa a nova dimensão do vetor v = (int *)realloc (v, m*sizeof(int)); Observação As seguintes notações são equivalentes: variavel[indice] equivale a *(variavel+indice) variavel[0] equivale a *variavel &variavel[indice] equivale a (variavel+indice ) Observação Ponteiros, vetores e matrizes são muito relacionados em C Vetores são ponteiros char nome[30] nome sozinho é um ponteiro para caracter, que aponta para a primeira posição do nome Matrizes de ponteiros Ponteiros podem ser declarados como vetores ou matrizes multidimensionais int *vetor[30]; //vetor de 30 ponteiros para inteiros int a =1, b=2, c=3; vetor[0] = &a; //vetor[0] aponta para a vetor[1] = &b; vetor[2] = &c; // imprime a:1, b:2 printf(‴a:%i, b:%i‵ ,*vetor[0], *vetor[1] ); Matrizes de ponteiros Manipulação de string: char *mensagem[] = ‴arquivo não encontrado‵ , ‴erro de leitura‵ , ‴erro de escrita‵ , ‴impossivel criar arquivo‵ }; void escreveMensagemDeErro(int num){ printf(‴%s\n‵ , mensagem[num]); } main(){ escreveMensagemDeErro(3); } Matrizes de ponteiros Importante: Quando alocamos um vetor de ponteiros para inteiros, não necessariamente estamos alocando espaço de memória para armazenar os valores inteiros! Ponteiro para ponteiro main(){ int x, *p, **q; x = 10; p = &x; q = &p; printf(‴%i\n‵ , **q); }