Baixe o app para aproveitar ainda mais
Prévia do material em texto
4/2/2020 Linguagem C 1 LTP II Ponteiros e Alocação Dinâmica de Memória 4/2/2020 Linguagem C 2 Alocação dinâmica de memória • Alocação dinâmica é o meio pelo qual um programa pode obter memória enquanto está em execução. • Em geral a alocação é utilizada quando não se sabe a quantidade de dados que serão armzanenados durante a execução do programa, o que requer tipos e estruturas de dados de qualquer tamanho e modificáveis durante a execução de programas; • Exemplos são matrizes dinâmicas e listas encadeadas. • A memória alocada dinamicamente é obtida do heap (região de memória que está entre o programa e a pilha). 4/2/2020 Linguagem C 3 Alocação dinâmica (malloc) • Funções para alocação dinâmica: #include <stdlib.h> void *malloc( size_t numero de bytes); aloca dinamicamente uma porção contínua da memória com tamanho igual ao número de bytes especificado retornando um ponteiro para o bloco alocado. Se não for possível alocar memória é retornado um ponteiro nulo (NULL). O ponteiro retornado é do tipo void, o que faz com que possa ser convertido em qualquer outro tipo de ponteiro em C. Exemplo: char *c; c= (char *) malloc (6); Retorna um ponteiro para uma área de memória de 6 bytes acessível por um ponteiro do tipo char. 4/2/2020 Linguagem C 4 Alocação dinâmica (malloc) • Dependendo do tipo de variável que se deseja armazenar, a quantidade de bytes necessário por variável a ser alocada varia; • Por exemplo, uma variável float necessita de quatro bytes, enquanto uma int de 2 ou 4 bytes; • Para facilitar a alocação de memória, pode-se utilizar a função sizeof (), cuja sintaxe é: – int sizeof(tipo) • Exemplos: malloc (10 * sizeof (int)); // aloca 20 bytes para 10 variáveis do tipo int malloc (10 * sizeof (float)); // aloca 40 bytes para 10 variáveis do tipo float 4/2/2020 Linguagem C 5 Alocação dinâmica (malloc) • Uma sintaxe importante no uso da função malloc é a conversão de tipo; • Alguns compiladores não aceitam que o ponteiro retornado pela função seja igualado a uma variável sem conversão; • Para evitar erros de sintaxe, é recomendável converter o tipo retornado da seguinte maneira: variável_ponteiro = (tipo_ponteiro *) malloc (...); • Exemplo: int *p; float *f; p = (int *) malloc (10 * sizeof (int)); f = (float *) malloc (10 * sizeof (float)); 4/2/2020 Linguagem C 6 Alocação dinâmica (malloc) • A função malloc não efetua inicialização da área de memória alocada. • Uma área de memória alocada utilizando malloc pode ser utilizada como uma matriz, cujo tamanho pode ser configurado em tempo de execução. • Exemplo: int *p; p = (int *) malloc (15 * sizeof (int)); *p=1; // ou p[0] = 1==> altera o valor do elemento p[0] *(p+2)=3; // ou p[2] = 3===>altera o valor do elemento p[2] printf(“p[0] = %d p[2] = %d\n”, p[0],p[2]); 4/2/2020 Linguagem C 7 Alocação dinâmica (malloc) • Podem ocorrer erros durante a alocação; por exemplo, pode não haver memória alocável disponível; • Caso o erro ocorra, o comando malloc retorna um ponteiro Nulo; • É recomendável que, após a alocação, seja efetuado um teste para checar se a alocação foi realizada com sucesso; • Exemplo: int *iptr; iptr = (int *)malloc(10 * sizeof(int)); if (iptr == NULL) { ...Tratamento do Erro... } 4/2/2020 Linguagem C 8 Alocação dinâmica (malloc) • Exercício – Implemente um cadastro de clientes de uma loja observando o seguinte: • Os dados dos clientes devem ser armazenados em um vetor; • A quantidade máxima não está definida. Deve ser informada pelo usuário no início do programa; • De cada cliente devem ser armazenados o nome e a idade; • No momento do cadastramento de cada cliente deve ser informado, pelo usuário, a quantidade máxima de caracteres do nome do cliente; • Devem ser implementadas as operações de cadastramento de clientes e consulta ao cadastro (pelo índice do vetor). 4/2/2020 Linguagem C 9 Alocação dinâmica (calloc) • Existe uma outra função análoga a malloc. Sintaxe: void *calloc( size_t numero itens,size_t tamanho do item); aloca dinamicamente uma porção contínua da memória com tamanho em bytes igual o produto de numero itens * tamanho de cada item, retornando um ponteiro para o bloco alocado. Se não for possível alocar memória é retornado um ponteiro nulo (NULL). O ponteiro retornado é do tipo void, o que faz com que possa ser convertido em qualquer outro tipo de ponteiro em C. A função calloc inicializa o bloco de dados alocados com 0 (zero). Exemplo : int *p; p=(int *) calloc (100, sizeof (int)); 4/2/2020 Linguagem C 10 Alocação dinâmica (realloc) • Blocos de Memória previamente alocados com malloc () e calloc() também podem ter ser tamanho alterado posteriormente com a função realloc(); Sintaxe : void *realloc (void *ptr, size_t numero de bytes); Modifica o tamanho da memória alocada para ptr para o novo tamanho especificado. Se o bloco de memória não puder ter seu tamanho alterado, a função realloc() alocará, se possível, um novo bloco de memória e copiando o conteúdo do bloco já existente para o novo bloco alocadao Se ptr é igual a NULL a realloc funciona igual a malloc. Se numero de bytes for zero, o ponteiro ptr é liberado análogo ao free. Se não houver memória suficiente a função retorna nulo e o bloco original é preservado. 4/2/2020 Linguagem C 11 Alocação dinâmica (free) • Após a utilização de um bloco de memória, o mesmo não é novamente alocado até ser liberado em tempo de execução com a função free; Sintaxe: void free( void *p); A função free toma um ponteiro como argumento e libera a memória para a qual o ponteiro aponta; Exemplo: int *iptr; iptr = (int *)malloc(10 * sizeof(int)); if (iptr == NULL) { ...Tratamento do Erro... } ......... free(iptr); 4/2/2020 Linguagem C 12 Alocação dinâmica (Uso de Malloc) char *pChar; int *pInt, nroChar, nroInt; printf(“ Numero de caracteres a serem alocados\n”); scanf(“%d”, &nroChar); if ( !(pChar =(char*) malloc (nroChar *sizeof(char)))) printf(“nao foi possivel alocar memoria\n”); else printf(“alocacao realizada com sucesso\n”); printf(“ Numero de elementos inteiros a alocar\n”); scanf(“%d”, &nroInt); if (pInt = (int*) calloc(nroInt, sizeof(int))){ for (i=0; i< nroInt) pInt[i] = i*i; printf(“valores\n”); for (i=0; i< nroInt) printf(“ %10d”, pInt[i]); printf(“\n”); } else printf(“erro de alocacao de memoria\n”); free (pChar); free (pInt); 4/2/2020 Linguagem C 13 Alocação dinâmica (Uso de Malloc) #include <stdio.h> #include <conio.h> #include <stdlib.h> void leMatriz(int *z, int n); void escreveMatriz( int *z, int n); void main (void) { int *x, nroElem; printf(“digite o nro de elementos a serem lidos \n”); scanf(“%d”, &nroElem); x= (int*) malloc(nroElem * sizeof(int)); if(x){ leMatriz (x,nroElem); escreveMatriz(x, nroElem); free(x);} else printf(“Erro de alocacao\n”); getch(); } void leMatriz(int *z, int n) { for (int i=0; i<n; i++) { printf(“Digite o elemento [%d] =”, i+1); scanf(“%d”, &z[i]); } } void escreveMatriz( int *z, int n) { printf(“Matriz lida \n”); for (int i=0; i<n;i++) printf(“%10d”, *(z+i)); printf(“\n”); } 4/2/2020 Linguagem C 14 Alocação dinâmica (Uso de Realloc) #include <stdio.h> #include <conio.h> #include <stdlib.h> void leMatriz(int *z, int n); void main(void) { float *p,*novop; int nroElem,novoNroElem; printf("Digite o numero de elementos da matriz = "); scanf("%d",&nroElem); p= (float *) malloc(nroElem*sizeof(float)); if (!p) printf("erro de alocacao dos %d elementos \n", nroElem); else { for (int i=0; i<nroElem;i++) p[i] = i+1; 4/2/2020 Linguagem C 15 Alocação dinâmica (Uso de Realloc) printf("Digite o novo numero de elementos da matriz = "); scanf("%d",&novoNroElem); novop= (float *) realloc(p, novoNroElem * sizeof(float)); if (!novop) { printf("erro de realocacao dos %d elementos \n", novoNroElem); free(p); } else{ p= novop; for(inti=nroElem;i<novoNroElem;i++) p[i] = i+1; for (int i=0; i<novoNroElem;i++) printf("Elemento [%4d] = %10.2f\n",i+1,p[i]); free (p);} } getch();} 4/2/2020 Linguagem C 16 Alocação dinâmica (Uso Calloc e Realloc) int num =10, *matriz,cont,*matriz2; if((matriz = (int *) calloc (num, sizeof(int))) { printf ("Os elementos atuais da matriz e seus enderecos sao:\n"); for (cont=0;cont < num;cont++) { matriz[cont]=cont; printf ("%d\t%x\n",matriz[cont],&matriz[cont]); } if((matriz 2= (int *) realloc (matriz, num-5)) { printf ("Apos a realocação, os elementos da matriz e seus enderecos sao:\n"); for (cont=0;cont < num-5;cont++){ matriz[cont]=cont*cont; printf ("%d\t%x\n",matriz[cont], &matriz[cont]); } free (matriz2); } else free(matriz); // erro de alocacao de matriz2 } 4/2/2020 Linguagem C 17 Ponteiros para ponteiros • Quando um ponteiro contém o endereço de uma variável dizemos que existe uma indireção simples. Exemplo : float *p, maior; p = &maior ; • Um ponteiro pode apontar para um outro ponteiro. Neste diz-se que temos uma indireção múltipla ou ponteiro para ponteiro. Endereço Valor Ponteiro Váriável Endereço Endereço Valor Ponteiro Ponteiro Variável 4/2/2020 Linguagem C 18 Ponteiros para ponteiros • Variáveis do tipo ponteiro para ponteiro são declaradas como : tipo_do_ponteiro ** nome_do_ponteiro; void main (void) { float a = 50.35, *pa, **ppa; pa = &a; // pa armazena o endereço da variável a ppa = &pa; // ppa armazena o endereço do ponteiro pa printf(“ a= %f \n”,a); // imprime o valor de a printf(“ a = %f\n”, *pa); // imprime o valor de a usando pa printf(“ a= %f\n”, **ppa); // imprime o valor de a usando ppa } 4/2/2020 Linguagem C 19 Ponteiros para ponteiros #include <stdio.h> #include <conio.h> #include <stdlib.h> void aloca (float **pMat, int n); void desaloca (float *pMat); void leNotas(float *notas, int nroAlunos); int main (void){ float *notas; int nroAlunos; printf("Digite o numero de alunos= "); scanf("%d", &nroAlunos); aloca (¬as, nroAlunos); if (!notas) { printf("Erro de alocacao\n"); exit(0); } leNotas(notas,nroAlunos); for (int i=0; i<nroAlunos;i++) printf("Nota [%d] = %.2f\n", i+1, notas[i]); desaloca(notas); getch(); } void aloca (float **pMat, int n){ *pMat = (float*) malloc(n * sizeof(float)); } void desaloca (float *pMat){ free(pMat); } void leNotas(float *notas, int nroAlunos){ for (int i=0; i<nroAlunos;i++){ printf("Digite a nota do aluno %d = ", i+1); scanf("%f",¬as[i]);}} 4/2/2020 Linguagem C 20 Matrizes de ponteiros • Ponteiros podem ser organizados em matrizes como qualquer outro tipo de dado. A declaração de uma matriz de ponteiros é realizada como: tipo_do_ponteiro *nome_do_ponteiro[Dimensão]; • Exemplo void main (void){ int nro1, nro2=60, *pNro[2]; pNro[0] = &nro1; pNro[1] = &nro2; printf("Digite um numero inteiro= "); scanf("%d",pNro[0]); printf(" nro1 = %d %d %d \n", nro1,*pNro[0], pNro[0][0]); printf(" nro2 = %d\n", *pNro[1]); } 4/2/2020 Linguagem C 21 Matrizes de Ponteiros (usando como matrizes bidimensionais) #include <stdio.h> #include <conio.h> #include <stdlib.h> int main (void){ int nCol,nLin; float *a[20]; // float a[20][nCol] printf("Digite o numero de linhas = "); scanf("%d", &nLin); // nLin deve ser menor que 20 printf("Digite o numero de colunas = "); scanf("%d", &nCol); for (int i=0; i<nLin;i++) { a[i] = (float *)malloc(nCol * sizeof(float) ); if (!a[i]){ printf("Erro na alocacao da linha %d \n"); getch();exit(0);}} for (int i=0; i< nLin; i++) { for (int j=0; j< nCol; j++) { printf("Digite A[%d,%d] = ",i+1,j+1); scanf("%f", &a[i][j]); } } for (int i=0; i< nLin; i++){ for (int j=0; j< nCol; j++) { printf("A[%d,%d] = %.3f \n",i+1,j+1,a[i][j]); } free(a[i]); } getch(); } 4/2/2020 Linguagem C 22 Ponteiros para Ponteiros (usando como matrizes bidimensionais) #include <stdio.h> #include <conio.h> #include <stdlib.h> int main (void) { int nCol,nLin; float **a; printf("Digite o numero de linhas = "); scanf("%d", &nLin); printf("Digite o numero de colunas = "); scanf("%d", &nCol); a = (float **) malloc(nLin * sizeof(float*)); if(!a) { printf("Erro na alocacao da matriz de linhas \n"); getch(); exit(0);} for (int i=0; i<nLin;i++){ a[i] = (float *) malloc(nCol * sizeof(float)); if (!a[i]){ printf("Erro na alocacao da linha %d \n",i); getch();exit(0);} for (int i=0; i< nLin; i++){ for (int j=0; j< nCol; j++){ printf("Digite A[%d,%d] = ",i+1,j+1); scanf("%f", &a[i][j]);}} for (int i=0; i< nLin; i++){ for (int j=0; j< nCol; j++){ printf("A[%d,%d] = %.3f \n",i+1,j+1,a[i][j]);} free(a[i]);} free(a); getch(); }
Compartilhar