Alocação Dinâmica de Structs
Parte da seção Logic & Flow do Journey de C da Coddy — lição 48 de 63.
Até agora, você aprendeu como criar structs na stack - elas existem dentro do escopo onde são declaradas e são limpas automaticamente quando esse escopo termina. Mas e se você precisar que uma struct persista além do seu escopo original, ou quando você não sabe em tempo de compilação de quantas structs precisará?
É aqui que entra a alocação dinâmica. Você pode usar malloc() para criar structs na heap, assim como faria para qualquer outro tipo de dado. A principal diferença é que structs alocadas dinamicamente permanecem na memória até que você as libere explicitamente com free().
Aqui está a sintaxe para alocar dinamicamente uma struct:
struct Point *ptr = malloc(sizeof(struct Point));Isso aloca memória suficiente no heap para conter uma struct Point e retorna um ponteiro para essa memória. Você pode então usar o operador de seta para acessar e modificar os membros da struct:
ptr->x = 10;
ptr->y = 20;Lembre-se de sempre verificar se o malloc() teve sucesso (retornou não-NULL) e de chamar free(ptr) quando terminar de usar a struct para evitar vazamentos de memória. Esta técnica é essencial para construir programas flexíveis que podem criar e gerenciar estruturas de dados em tempo de execução.
Desafio
FácilCrie um programa em C que demonstre a alocação dinâmica de structs usando malloc(). Seu programa deve:
- Definir uma
structchamadaCarcom os seguintes membros:- Um inteiro
yearpara armazenar o ano de fabricação - Um array de caracteres
brandcom tamanho 20 para armazenar a marca do carro - Um array de caracteres
modelcom tamanho 25 para armazenar o modelo do carro - Um float
pricepara armazenar o preço do carro - Um inteiro
mileagepara armazenar a quilometragem do carro
- Um inteiro
- Na função principal, declarar um ponteiro para uma struct
CarchamadocarPtr - Usar
malloc()para alocar dinamicamente memória para uma structCare atribuir o endereço retornado acarPtr - Verificar se a alocação de memória foi bem-sucedida:
- Se
carPtrforNULL, imprimaMemory allocation failede encerre o programa - Se a alocação for bem-sucedida, imprima
Memory allocation successful
- Se
- Ler os seguintes valores de entrada e atribuí-los aos membros da struct usando o operador de seta:
- Ler um inteiro para o ano e atribuí-lo usando
carPtr->year - Ler uma string para a marca e atribuí-la usando
carPtr->brand - Ler uma string para o modelo e atribuí-la usando
carPtr->model - Ler um float para o preço e atribuí-lo usando
carPtr->price - Ler um inteiro para a quilometragem e atribuí-lo usando
carPtr->mileage
- Ler um inteiro para o ano e atribuí-lo usando
- Após ler todos os valores, realizar os seguintes cálculos usando o operador de seta:
- Calcular a idade do carro subtraindo o ano de 2024:
int age = 2024 - carPtr->year; - Calcular a taxa de depreciação baseada na idade: se a idade for maior que 10, defina a depreciação como 0.6, caso contrário, defina-a como 0.8
- Calcular o valor atual:
carPtr->price * depreciation
- Calcular a idade do carro subtraindo o ano de 2024:
- Imprimir as informações do carro usando o operador de seta neste formato exato:
Car Information:Year: [year]Brand: [brand]Model: [model]Original Price: [price]Mileage: [mileage]Age: [age] yearsCurrent Value: [current_value]
- Liberar a memória alocada dinamicamente usando
free(carPtr) - Imprimir
Memory freed successfully
Este desafio testa sua compreensão da alocação dinâmica de structs usando malloc(), a verificação de falhas na alocação, o acesso a membros de structs através de ponteiros usando o operador de seta e a liberação adequada da memória alocada com free(). Você praticará o ciclo de vida completo do gerenciamento dinâmico de memória com structs.
Folha de consulta
Use malloc() para alocar structs dinamicamente no heap:
struct Point *ptr = malloc(sizeof(struct Point));Acesse membros de structs através de ponteiros usando o operador de seta:
ptr->x = 10;
ptr->y = 20;Sempre verifique se malloc() teve sucesso e libere a memória quando terminar:
if (ptr == NULL) {
// Tratar falha de alocação
}
// Use a struct...
free(ptr);Experimente você mesmo
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// TODO: Defina a struct Car aqui
int main() {
// TODO: Declare um ponteiro para a struct Car chamado carPtr
// TODO: Use malloc() para alocar memória para uma struct Car
// TODO: Verifique se a alocação de memória foi bem-sucedida
// Leia os valores de entrada
int year, mileage;
char brand[20], model[25];
float price;
scanf("%d", &year);
scanf("%s", brand);
scanf("%s", model);
scanf("%f", &price);
scanf("%d", &mileage);
// TODO: Atribua os valores de entrada aos membros da struct usando o operador de seta
// TODO: Calcule a idade, depreciação e valor atual
// TODO: Imprima as informações do carro no formato exigido
// TODO: Libere a memória alocada e imprima uma mensagem de sucesso
return 0;
}Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Logic & Flow
1Fundamentos de Ponteiros
O que é um Ponteiro?Declarando PonteirosO Operador de Endereço (&)O Operador de Desreferência (*)Ponteiros NULLRecapitulação: Fundamentos de Ponteiros4Projeto: Utilitário de Texto Simples
Visão Geral do ProjetoContando Caracteres2Ponteiros e Arrays
Nomes de Arrays como PonteirosElementos de Array - PonteirosAritmética de PonteirosComparando PonteirosRecapitulação: Percorrendo Arrays com Ponteiros5Ponteiros e Funções
Passagem por ValorPassando Ponteiros para FunçõesModificando Variáveis via PonteirosUm Exemplo Clássico: SwapPassando Arrays para FunçõesRecapitulação: Ponteiros como Argumentos8Structs e Ponteiros
Ponteiros para StructsO Operador Seta (->)Passagem de Structs por ValorPassagem de Ponteiros para StructsAlocação Dinâmica de StructsRecapitulação: Modificando Struct - Ptr3Arrays de Caracteres e Strings
Strings como Arrays de charO Terminador NuloEntrada de Strings com scanfUsando strlen()Usando strcpy()Usando strcat()Usando strcmp()Recapitulação: Funções Básicas de Strings6Gerenciamento de Memória
Memória Stack vs. HeapAlocação Dinâmica - malloc()Usando sizeof() para AlocaçãoVerificando Falhas de AlocaçãoLiberando Memória com free()Alocando com calloc()Recapitulação: Array Dinâmico9Projeto: Cadastro Simples de Contatos
Projeto: Definir a Struct de ContatoFunção para Criar um Contato