Buscar

[INF1007] Resumo Alocação Dinâmica

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 6 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 6 páginas

Prévia do material em texto

Programação II 
Monitor: André Vicente Pessanha 
Resumo Alocação Dinâmica: 
 
*************************************************************************************************** 
 
OBS:​ Essa matéria > só < é cobrada na P1, P2 e P3! :D 
 
************************************************************************************************** 
 
- Definição: 
 
Em termos bem simples: Alocação dinâmica é uma forma de "pedir emprestado" memória 
para o Pc através de uma função chamada >> malloc << que recebe como parâmetro a >> 
quantidade exata de memória << que você precisa e retorna um ponteiro genérico que 
"aponta" para o local onde está a memória emprestada. 
 
 
Exemplo: Vamos criar um vetor que armazena 10 notas: 
 
- Sem usar alocação dinâmica (Prog 1) 
 
float notas[10]; 
 
for(i=0;i<10;i++){ 
 puts("Digite a nota: "); 
 scanf("%f",&notas[i]); 
} 
 
 
- Usando alocação dinâmica: 
 
 
float * notas; 
 
notas = (float *) malloc (10 * sizeof(float)); 
if(!notas){ 
 puts("Erro! Sem memoria!"); 
 exit(1); 
} 
 
 
Primeiro declaramos um ponteiro para float. Depois chamamos a função malloc, passando a 
quantidade de memória que precisamos. (Em bytes) 
 
OBS:​ A quantidade de bytes de um float pode variar de sistema pra sistema, então existe 
uma função chamada >> sizeof << que nos diz exatamente a quantidade de bytes de 
qualquer tipo! 
 
E como precisamos armazenar 10 notas, são 10 valores do tipo float, certo? 
É só colocar 10 * sizeof( float), ou seja, 10 vezes o tamanho de um float! 
 
OBS:​ Na historinha do começo, eu disse que a função malloc retorna um >> Ponteiro 
Genérico << né? É justamente pelo fato de ser genérico que precisamos converter ele pro 
formato que a gente precisa! (float *) malloc 
 
OBS2:​ Lembra quando enviamos um vetor como parâmetro? 
 
EX: float calcula_total (float notas[], int n); 
 
Uma outra forma de escrever esse parâmetro é: float * notas 
 
Isso é possível porque quando enviamos qualquer vetor como parâmetro, na verdade não 
estamos enviando uma cópia do vetor e sim um ponteiro que "aponta" pro começo do vetor! 
(Primeira posição) 
 
OBS:​ Se caso a função malloc não conseguir pegar a memória emprestada, ela vai retornar 
um ponteiro Nulo, então >> SEMPRE << precisamos colocar uma prevenção de erro! Pois 
se o vetor notas for NULL não faz o menor sentido continuar! Nesse caso temos que 
encerrar o programa inteiro ou no mínimo a função auxiliar que chamou a malloc! 
 
if(!notas){ 
 puts("Erro! Sem memoria!"); 
 exit(1); 
} 
 
OBS:​ Lembrando que if(!notas) é uma forma bem mais simples de escrever if(notas == 
NULL) 
 
Para manipular o vetor é >>exatamente<< como se tivesse sido criado da forma tradicional! 
 
for(i=0;i<10;i++){ 
 puts("Digite a nota: "); 
 scanf("%f",&notas[i]); 
} 
 
OBS:​ >>SEMPRE<< que terminar de usar algo alocado dinamicamente, >>NUNCA<< se 
esqueça de devolver a memória para o sistema! 
 
 
 
free(notas); 
 
Lembra que a memória era emprestada? :D 
Pois é, eu sei que é triste, mas temos que devolver! :( 
A multa da correção é de aproximadamente -0.1 por esquecimento! Cuidado! 
 
------------------------------------------------------- // ------------------------------------------------------------ 
 
 
 
- Mas porque não criar um vetor sempre da maneira tradicional? 
 
 
O método tradicional continua valendo, mas além do enunciado exigir o uso de alocação 
dinâmica, vamos pensar na seguinte situação: 
 
Em todos os enunciados das provas em Prog 1 era dado a quantidade máxima de algo, 
notas por exemplo. Lembrando que ao declarar um vetor, é obrigatório especificar um 
tamanho máximo: 
 
EX: float notas[10]; 
 
Mas e se for um usuário que digita essa quantidade durante a execução do programa? 
 
É exatamente nesses casos que é essencial usar alocação dinâmica! 
 
 
------------------------------------------------------- // ------------------------------------------------------------ 
 
 
 
Ex 2: Enunciado pede pra criar uma função chamada Duplica que recebe como parâmetro 
uma string e que você aloque dinamicamente uma string, copie o conteúdo da string 
recebida e retorne o ponteiro para a nova string alocada: 
 
 
char * Duplica (char *frase){ 
 int tam; 
 char *nova; 
 
 tam = strlen (frase); 
 nova = (char *) malloc (tam + 1); 
 if(!nova){ 
 puts("Sem memoria!"); 
 return NULL; 
 } 
 strcpy(nova, frase); 
 return nova; 
} 
 
int main (void) { 
 char frase[] = "Fritas eh um alimento saudavel"; 
 char *copia; 
 
 copia = Duplica (frase); 
 if (!copia) { 
 puts("Nao conseguiu duplicar a string!"); 
 exit(1); 
 } 
 printf("Original: %s\nCopia: %s\n", frase, copia); 
 free(copia); 
 return 0; 
} 
 
Primeiro vamos analisar o protótipo dessa função: 
 
char * Duplica (char *frase); 
 
Ela recebe como parâmetro uma string, lembrando que um vetor é representado pelo 
endereço do primeiro elemento! Então escrever char *frase é >> o mesmo << que escrever 
char frase[], assim como em qualquer vetor! 
 
E o retorno dela é char * , ou seja, ela retorna um ponteiro para char! 
Apesar de chamar "Ponteiro para char", na verdade se trata de um String, pois como já 
relembramos, toda String é sempre representada por um ponteiro que "aponta" pro primeiro 
elemento, ou seja, um caracter! 
 
OBS: >>SEMPRE<< que uma função tiver esse ou um tipo de retorno parecido (int *, float *, 
char *, etc), mesmo que o enunciado não especifique, será sempre alocação dinâmica! 
(Tirando os casos em que o enunciado diz para não usar alocação dinâmica) 
 
Antes de usar a função malloc, precisamos declarar um ponteiro para char: 
 
char *nova; 
 
Lembra que a função malloc recebe a quantidade de bytes como parâmetro? 
 
Mas como cada caracter (cada letra da string) possui exatamente >> um << byte, então o 
primeiro passo é armazenar a quantidade de caracteres (tamanho) através da função strlen! 
 
tam = strlen(frase); 
nova = (char *) malloc (tam + 1); 
 
OBS:​ Lembra que pra ser uma string, precisa >>obrigatoriamente<< terminar com '\0'? 
Por isso usamos tam + 1 que é justamente o espaço necessário para o '\0' ! 
 
Outra forma mais prática: nova = (char *) malloc (strlen(frase) + 1); 
 
Logo em seguida vem a nossa prevenção de erro: 
 
if(!nova){ 
 puts("Sem memoria!"); 
 return NULL; 
} 
 
OBS:​ Percebe que dessa vez não usei a função exit pra encerrar o programa ? 
 
Se a função retorna um ponteiro para algo e a malloc não conseguiu a memória 
emprestada, o correto é retornar o valor NULL! Em outras palavras, a decisão de encerrar o 
programa deve ser sempre de quem chamou a função (a função main no caso) e nunca da 
função auxiliar! 
 
Se não retornou NULL é porque deu tudo certo no empréstimo de memória. Então é só 
copiar o contéudo através da função strcpy e retornar esse novo ponteiro para string! 
 
Duas observações importantes sobre a main: 
 
- Se chamamos uma função que retorna um ponteiro para algo, precisamos de um local 
para armazenar o retorno, certo? 
 
char *copia; 
 
copia = Duplica (frase); 
 
 
Percebe que na main tratamos se o retorno da função foi NULL e > somente < nela que 
podemos encerrar o programa? 
 
if (!copia) { 
 puts("Nao conseguiu duplicar a string!"); 
 exit(1); 
} 
 
OBS: ​Não é que seja errado encerrar o programa na função auxiliar...Mas isso depende 
muito da correção de cada professor. Levando em conta que a mais boazinha de todas 
recomenda fazer assim, então melhor nem arriscar, né não? :) 
 
 
 
E pra fechar com chave de ouro, nunca esqueça de devolver a memória emprestada! 
 
free(copia); 
 
OBS: Apesar da main não ter alocado dinamicamente a string, ela recebeu o endereço 
(ponteiro) da memória alocada e armazenou na variável "copia" né? Agora a variável"copia" 
também "aponta" para a memória que foi alocada! Por isso podemos devolver ela usando a 
função free! 
 
 
------------------------------------------------------- // ------------------------------------------------------------

Continue navegando