1 / 19

Alocação Dinâmica de Memória

Alocação Dinâmica de Memória. David Menotti Algoritmos e Estruturas de Dados I DECOM – UFOP. Alocação Estática x Dinâmica. C: dois tipos de alocação de memória: Estática e Dinâmica.

carney
Download Presentation

Alocação Dinâmica de Memória

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Alocação Dinâmica de Memória David Menotti Algoritmos e Estruturas de Dados I DECOM – UFOP

  2. Alocação Estática x Dinâmica • C: dois tipos de alocação de memória: Estática e Dinâmica • Na alocação estática, o espaço para as variáveis é reservado no início da execução, não podendo ser alterado depois • int a; int b[20]; • Na alocação dinâmica, o espaço para as variáveis pode ser alocado dinamicamente durante a execução do programa Algoritmos e Estrutura de Dados I

  3. Alocação Dinâmica • As variáveis alocadas dinamicamente são chamadas de Apontadores (pointers) pois na verdade elas armazenam o endereço de memória de uma variável • A memória alocada dinamicamente faz parte de uma área de memória chamada heap • Basicamente, o programa aloca e desaloca porções de memória do heap durante a execução Algoritmos e Estrutura de Dados I

  4. Esquema de Memória Algoritmos e Estrutura de Dados I

  5. Acesso a partir de Apontadores • Acessar o valor da variável: endereço de memória armazenado • Acessar o conteúdo que associado ao endereço de memória armazenado Algoritmos e Estrutura de Dados I

  6. Liberação de Memória • A memória deve ser liberada após o término de seu uso • A liberação deve ser feita por quem fez a alocação: • Estática: compilador • Dinâmica: programador Algoritmos e Estrutura de Dados I

  7. Apontadores – Notação (c) • definição de p como um apontador para uma variável do tipo Tipo • Tipo *p; • Alocação de memória para uma variável apontada por p • p = (Tipo*) malloc(sizeof(Tipo)); • Liberação de memória • free(p); • Conteudo da variável apontada por P • *p; • Valor nulo para um apontador • NULL; • Endereço de uma variável a • &a; Algoritmos e Estrutura de Dados I

  8. b a Alocação Estática Heap Alocação Dinâmica int *a, b; ... b = 10; a = (int *) malloc(sizeof(int)); *a = 20; a = &b; 10 X 20 Algoritmos e Estrutura de Dados I

  9. Erros Comuns • Esquecer de alocar memória e tentar acessar o conteúdo da variável • Copiar o valor do apontador ao invés do valor da variável apontada • Esquecer de desalocar memória • Ela é desalocada ao fim do programa ou procedimento função onde a variável está declarada, mas pode ser um problema em loops • Tentar acessar o conteúdo da variável depois de desalocá-la Algoritmos e Estrutura de Dados I

  10. double a; double *p; a = 3.14; printf("%lf\n", a); p = &a; *p = 2.718; printf("%lf\n", a); a = 5.; printf("%lf\n", *p); p = NULL; p = (double *)malloc(sizeof(double)); *p = 20.; printf("%lf\n", *p); printf("%lf\n", a); free(p); printf("%lf\n", *p); Exercício: C Algoritmos e Estrutura de Dados I

  11. Pergunta que não quer calar... int *a não é a declaração de um vetor de int? • Em C, todo apontador pode se comportar como vetor: • Portanto pode-se fazer coisas como: int a[10], *b; b = a;b[5] = 100; printf(“%d\n”, a[5]); printf(“%d\n”, b[5]); int a[10], *b; b = (int *) malloc(10*sizeof(int));b[5] = 100; printf(“%d\n”, a[5]); printf(“%d\n”, b[5]); Obs. Não se pode fazer a = b no exemplo acima 100 100 42657 100 Algoritmos e Estrutura de Dados I

  12. Apontadores para Tipos Estruturados • Apontadores são normalmente utilizados com tipos estruturados Typedef struct { int idade; double salario; } TRegistro; TRegistro *a; ... a = (TRegistro *) malloc(sizeof(TRegistro)) a->idade = 30; /* *a.idade = 30 */ a->salario = 80; Algoritmos e Estrutura de Dados I

  13. Passagem de Parâmetros • Em pascal, parâmetros para função podem ser passados por valor ou por referência • Por valor: o parâmetro formal (recebido no procedimento) é uma cópia do parâmetro real (passado na chamada) • Por referência: o parâmetro formal (recebido no procedimento) é uma referência para o parâmetro real (passado na chamada) • Usa-se o termo var precedendo o parâmetro formal • Em C só existe passagem por valor, logo deve-se implementar a passagem por referência utilizando-se apontadores Algoritmos e Estrutura de Dados I

  14. Passagem de Parâmetros (C) void SomaUm(int x, int *y) { x = x + 1; *y = (*y) + 1; printf("Funcao SomaUm: %d %d\n", x, *y); } int main() { int a=0, b=0; SomaUm(a, &b); printf("Programa principal: %d %d\n", a, b); } 1 1 0 1 Algoritmos e Estrutura de Dados I

  15. Passagem de Parâmetros • E para alocar memória dentro de um procedimento? • Em pascal, basta passar a variável (apontador) como referência. • Em C também, mas como não há passagem por referência as coisas são um pouco mais complicadas void aloca(int **x, int n) { *x=(int *)malloc(n*sizeof(int)); *x[0] = 20; } int main() { int *a; aloca(&a, 10); a[1] = 40; } void aloca(int *x, int n) { x=(int *)malloc(n*sizeof(int)); x[0] = 20; } int main() { int *a; aloca(a, 10); a[1] = 40; } Error! Access Violation! OK Algoritmos e Estrutura de Dados I

  16. Exercício 1 • Criar um tipo que é uma estrutura que represente uma pessoa, contendo nome, data de nascimento e CPF. • Criar uma variável que é um ponteiro para esta estrutura (no programa principal) • Criar uma função que recebe este ponteiro e preenche os dados da estrutura • Criar uma função que recebe este ponteiro e imprime os dados da estrutura • Fazer a chamada a estas funções na função principal Algoritmos e Estrutura de Dados I

  17. Exercício 2 1. Faça um programa que leia um valor n, crie dinamicamente um vetor de n elementos e passe esse vetor para uma função que vai ler os elementos desse vetor. 2. Declare um TipoRegistro, com campos a inteiro e b que é um apontador para char. No seu programa crie dinamicamente uma váriavel do TipoRegistro e atribua os valores 10 e ‘x’ aos seus campos. Algoritmos e Estrutura de Dados I

  18. Respostas (1) void LeVetor(int *a, int n){ int i; for(i=0; i<n; i++) scanf("%d",&a[i]); } int main(int argc, char *argv[]) { int *v, n, i; scanf("%d",&n); v = (int *) malloc(n*sizeof(int)); LeVetor(v,n); for(i=0; i<n; i++) printf("%d\n",v[i]); } Apesar do conteúdo ser modificado Não é necessário passar por referência pois todo vetor já é um apontador... Algoritmos e Estrutura de Dados I

  19. Respostas (2) É necessário alocar espaço para o registro e para o campo b. *(reg->b) representa o conteúdo da variável apontada por reg-> typedef struct { int a; char *b; } TRegistro; int main(int argc, char *argv[]) { TRegistro *reg; reg = (TRegistro *) malloc(sizeof(TRegistro)); reg->a = 10; reg->b = (char *) malloc(sizeof(char)); *(reg->b) = 'x'; printf("%d %c",reg->a, *(reg->b)); } Algoritmos e Estrutura de Dados I

More Related