Динамическое выделение памяти для структур
Часть раздела Logic & Flow путешествия по C на Coddy — урок 48 из 63.
До сих пор вы узнали, как создавать структуры в стеке — они существуют в той области видимости, где они объявлены, и автоматически удаляются по её завершении. Но что, если вам нужно, чтобы структура сохранялась за пределами своей исходной области видимости, или если вы не знаете во время компиляции, сколько структур вам потребуется?
Вот здесь и появляется динамическое распределение памяти. Вы можете использовать malloc() для создания структур в куче, точно так же, как и для любого другого типа данных. Ключевое отличие заключается в том, что динамически распределенные структуры остаются в памяти до тех пор, пока вы явно не освободите их с помощью free().
Вот синтаксис для динамического выделения памяти для структуры:
struct Point *ptr = malloc(sizeof(struct Point));Это выделяет в куче достаточно памяти для хранения одной структуры Point и возвращает указатель на эту память. Затем вы можете использовать оператор «стрелка» для доступа к членам структуры и их изменения:
ptr->x = 10;
ptr->y = 20;Не забывайте всегда проверять, успешно ли выполнилась функция malloc() (вернула значение, отличное от NULL), и вызывать free(ptr), когда вы закончите работу со структурой, чтобы предотвратить утечки памяти. Этот метод необходим для создания гибких программ, которые могут создавать структуры данных и управлять ими во время выполнения.
Задание
ЛегкоСоздайте программу на языке C, которая демонстрирует динамическое выделение памяти для структур с использованием malloc(). Ваша программа должна:
- Определить
structс именемCarсо следующими полями:- Целое число
yearдля хранения года выпуска - Символьный массив
brandразмером 20 для хранения марки автомобиля - Символьный массив
modelразмером 25 для хранения модели автомобиля - Число с плавающей точкой
priceдля хранения цены автомобиля - Целое число
mileageдля хранения пробега автомобиля
- Целое число
- В функции main объявите указатель на структуру
Carс именемcarPtr - Используйте
malloc()для динамического выделения памяти для одной структурыCarи присвойте возвращенный адрес указателюcarPtr - Проверьте, было ли выделение памяти успешным:
- Если
carPtrравенNULL, выведитеMemory allocation failedи завершите программу - Если выделение памяти прошло успешно, выведите
Memory allocation successful
- Если
- Считайте следующие входные значения и присвойте их полям структуры, используя оператор стрелка:
- Считайте целое число для года и присвойте его с помощью
carPtr->year - Считайте строку для марки и присвойте ее с помощью
carPtr->brand - Считайте строку для модели и присвойте ее с помощью
carPtr->model - Считайте число с плавающей точкой для цены и присвойте его с помощью
carPtr->price - Считайте целое число для пробега и присвойте его с помощью
carPtr->mileage
- Считайте целое число для года и присвойте его с помощью
- После считывания всех значений выполните следующие вычисления, используя оператор стрелка:
- Вычислите возраст автомобиля, вычтя год выпуска из 2024:
int age = 2024 - carPtr->year; - Рассчитайте коэффициент амортизации в зависимости от возраста: если возраст больше 10 лет, установите амортизацию равной 0.6, в противном случае — 0.8
- Вычислите текущую стоимость:
carPtr->price * depreciation
- Вычислите возраст автомобиля, вычтя год выпуска из 2024:
- Выведите информацию об автомобиле, используя оператор стрелка, в следующем формате:
Car Information:Year: [year]Brand: [brand]Model: [model]Original Price: [price]Mileage: [mileage]Age: [age] yearsCurrent Value: [current_value]
- Освободите динамически выделенную память с помощью
free(carPtr) - Выведите
Memory freed successfully
Эта задача проверяет ваше понимание динамического выделения памяти для структур с помощью malloc(), проверки ошибок выделения памяти, доступа к полям структуры через указатели с помощью оператора стрелка и правильного освобождения выделенной памяти с помощью free(). Вы попрактикуетесь в полном жизненном цикле управления динамической памятью со структурами.
Шпаргалка
Используйте malloc() для динамического выделения памяти под структуры в куче:
struct Point *ptr = malloc(sizeof(struct Point));Обращайтесь к членам структуры через указатели, используя оператор «стрелка»:
ptr->x = 10;
ptr->y = 20;Всегда проверяйте, успешно ли выполнилась malloc(), и освобождайте память по завершении работы:
if (ptr == NULL) {
// Обработка ошибки выделения памяти
}
// Использование структуры...
free(ptr);Попробуйте сами
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// TODO: Определите структуру Car здесь
int main() {
// TODO: Объявите указатель на структуру Car с именем carPtr
// TODO: Используйте malloc() для выделения памяти для одной структуры Car
// TODO: Проверьте, было ли выделение памяти успешным
// Считайте входные значения
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: Присвойте входные значения членам структуры, используя оператор стрелка
// TODO: Рассчитайте возраст, амортизацию и текущую стоимость
// TODO: Выведите информацию об автомобиле в требуемом формате
// TODO: Освободите выделенную память и выведите сообщение об успехе
return 0;
}В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Logic & Flow
1Основы указателей
Что такое указатель?Объявление указателейОператор взятия адреса (&)Оператор разыменования (*)Указатели NULLИтоги: Основы указателей4Проект: Простая текстовая утилита
Обзор проектаПодсчет символов2Указатели и массивы
Имена массивов как указателиЭлементы массива — указателиАрифметика указателейСравнение указателейИтоги: Обход массива через указатели5Указатели и функции
Передача по значениюПередача указателей в функцииИзменение переменных через указателиКлассический пример: SwapПередача массивов в функцииИтоги: указатели как аргументы функций8Структуры и указатели
Указатели на структурыОператор «стрелка» (->)Передача структур по значениюПередача указателей на структурыДинамическое выделение памяти для структурИтоги: Изменение структур через указатели11Итоговые задачи на повторение
Повторение: динамическая конкатенация строкПовторение: массив структурПовторение: счетчик частоты слов3Символьные массивы и строки
Строки как массивы charНуль-терминаторВвод строк с помощью scanfИспользование strlen()Использование strcpy()Использование strcat()Использование strcmp()Итоги: основные строковые функции