Menu
Coddy logo textTech

Инициализация в стеке

Часть раздела Object Oriented Programming путешествия по C на Coddy — урок 14 из 61.

Не каждому объекту нужно находиться в куче. Когда структура невелика и имеет короткий жизненный цикл, выделение её в стеке проще и быстрее — ни malloc, ни free, никакого риска утечек памяти.

Вместо возврата указателя, фабричная функция может возвращать структуру по значению. Вся структура копируется вызывающей стороне:

typedef struct {
    int x;
    int y;
} Point;

Point create_point(int x, int y) {
    Point p;
    p.x = x;
    p.y = y;
    return p;
}

Вызывающая сторона получает полностью инициализированную копию:

Point origin = create_point(0, 0);
Point cursor = create_point(100, 50);
printf("Cursor: (%d, %d)\n", cursor.x, cursor.y);

Никаких указателей, очистка не требуется. Когда origin и cursor выходят из области видимости, они автоматически уничтожаются.

Этот подход лучше всего работает для небольших структур без динамически распределяемых членов. Для более крупных объектов или объектов, содержащих указатели на память в куче, паттерн конструктора с malloc остается лучшим выбором.

challenge icon

Задание

Легко

Давайте создадим модуль Temperature, который создает показания температуры в стеке с помощью фабричной функции. В отличие от конструкторов на основе кучи из предыдущих уроков, этот подход возвращает структуру по значению — без malloc, без free, простое и эффективное выделение памяти в стеке.

Вы создадите три файла:

  • temperature.h: Объявите структуру Temperature с двумя полями: double celsius и char scale (для хранения 'C' для Цельсия). Также объявите две функции:
    • create_temperature — принимает значение double и возвращает структуру Temperature по значению (не указатель!)
    • temperature_to_fahrenheit — принимает const Temperature * и возвращает эквивалентную температуру в Фаренгейтах в виде double
    Используйте include guards с символом TEMPERATURE_H.
  • temperature.c: Реализуйте обе функции. Ваша фабричная функция должна создать локальную переменную Temperature, инициализировать ее поля (установить scale в 'C') и вернуть ее. Формула преобразования: fahrenheit = celsius * 9.0 / 5.0 + 32.0
  • main.c: Используйте свою фабричную функцию для создания показания температуры и выведите значения как в Цельсиях, так и в Фаренгейтах.

Вы получите один входной параметр: температуру в градусах Цельсия (в виде double).

В вашем основном файле используйте create_temperature для создания структуры Temperature с заданным значением. Затем выведите исходное значение в Цельсиях и его эквивалент в Фаренгейтах.

Выведите результат в следующем формате:

Celsius: {celsius}
Fahrenheit: {fahrenheit}

Используйте %.2f для обоих значений, чтобы отобразить два знака после запятой.

Например, при входном значении 25.0 вывод будет следующим:

Celsius: 25.00
Fahrenheit: 77.00

Обратите внимание, насколько чист этот подход — вы получаете полностью инициализированную структуру без каких-либо забот об управлении памятью. Когда ваша переменная Temperature выходит за пределы области видимости, она очищается автоматически.

Шпаргалка

Фабричные функции могут возвращать структуры по значению вместо указателей. Это размещает структуру в стеке — без malloc, без free и без утечек памяти.

Пример фабричной функции, возвращающей значение:

typedef struct {
    int x;
    int y;
} Point;

Point create_point(int x, int y) {
    Point p;
    p.x = x;
    p.y = y;
    return p;
}

Использование фабричной функции:

Point origin = create_point(0, 0);
Point cursor = create_point(100, 50);
printf("Cursor: (%d, %d)\n", cursor.x, cursor.y);

Структура копируется вызывающей стороне и автоматически уничтожается при выходе из области видимости. Этот подход лучше всего подходит для небольших структур без динамически выделяемых членов.

Попробуйте сами

#include <stdio.h>
#include "temperature.h"

int main() {
    double celsius_input;
    scanf("%lf", &celsius_input);
    
    // TODO: Используйте create_temperature для создания структуры Temperature
    
    // TODO: Выведите значение Celsius, используя формат %.2f
    
    // TODO: Используйте temperature_to_fahrenheit для преобразования и вывода значения Fahrenheit
    
    return 0;
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Object Oriented Programming