0Pricing
C Academy · Урок

Изменение размера с realloc

Изменяйте размер динамического массива.

«Изменение размера с realloc» — бесплатный урок C Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C Academy содержит 4 уроков всего.

Когда одного malloc недостаточно

Иногда Вы выделяете массив, заполняете его, а затем обнаруживаете, что места нужно больше. Нельзя просто записывать данные за его конец.

realloc позволяет изменить размер существующего блока в куче, сохранив уже находящиеся в нём данные.

Сигнатура realloc

realloc(ptr, new_bytes) принимает старый указатель и новый общий размер в байтах.

Она возвращает указатель на блок нового размера. Начальная часть данных сохраняется до меньшего из старого и нового размеров.

int *bigger = realloc(a, new_n * sizeof(*a));

Блок может переместиться

realloc может увеличить блок на месте или выделить новый блок, скопировать данные и освободить старый.

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

a = realloc(a, new_n * sizeof(*a));
/* the old value of a may no longer be valid */

Опасность присваивания самому себе

Запись a = realloc(a, ...) выглядит аккуратно, но опасна: если realloc вернёт NULL, Вы перезапишете a и потеряете исходный указатель, оставив старый блок неосвобождённым.

Вместо этого используйте временную переменную.

int *tmp = realloc(a, new_n * sizeof(*a));
if (tmp == NULL) { /* a is still valid */ return 1; }
a = tmp;

Безопасное увеличение массива

Эта программа выделяет место для 3 переменных типа int, а затем увеличивает его до 6 с помощью realloc, сохраняя первые три значения.

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int *a = malloc(3 * sizeof(*a));
    if (!a) return 1;
    for (int i = 0; i < 3; i++) a[i] = i + 1;

    int *tmp = realloc(a, 6 * sizeof(*a));
    if (!tmp) { free(a); return 1; }
    a = tmp;

    for (int i = 3; i < 6; i++) a[i] = i + 1;
    for (int i = 0; i < 6; i++) printf("%d\n", a[i]);
    free(a);
    return 0;
}

Новые байты не инициализируются

При увеличении блока дополнительное место в конце содержит произвольные данные, как и свежая память, полученная через malloc.

realloc сохраняет старые данные, но не обнуляет новую область. Инициализируйте её до чтения.

a = realloc(a, 6 * sizeof(*a));
for (int i = 3; i < 6; i++) a[i] = 0;  /* clear new slots */

Стратегия удвоения

Вызов realloc для каждого отдельного элемента работает медленно. Классический приём — удваивать вместимость всякий раз, когда место заканчивается.

Так количество перераспределений остаётся небольшим по мере роста массива, обеспечивая хорошую среднюю производительность.

if (count == cap) {
    cap = cap ? cap * 2 : 4;
    int *tmp = realloc(a, cap * sizeof(*a));
    if (!tmp) { free(a); return 1; }
    a = tmp;
}

Построение массива добавлением элементов

Эта программа начинает с пустого массива и добавляет числа, при необходимости удваивая вместимость.

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int *a = NULL;
    size_t count = 0, cap = 0;
    for (int v = 1; v <= 5; v++) {
        if (count == cap) {
            cap = cap ? cap * 2 : 2;
            int *tmp = realloc(a, cap * sizeof(*a));
            if (!tmp) { free(a); return 1; }
            a = tmp;
        }
        a[count++] = v;
    }
    for (size_t i = 0; i < count; i++) printf("%d\n", a[i]);
    free(a);
    return 0;
}

realloc(NULL, n) работает как malloc

Если передать NULL в качестве указателя, realloc ведёт себя точно так же, как malloc.

Поэтому начальное присваивание a = NULL работает в цикле удвоения: самый первый realloc выделяет исходный блок.

int *a = NULL;
a = realloc(a, 4 * sizeof(*a));  /* same as malloc(4 * sizeof(*a)) */

Уменьшение блока

realloc также может уменьшить размер блока. Данные до нового размера сохраняются, а остальные отбрасываются.

Уменьшение может вернуть часть памяти системе, хотя реализации вправе сохранить блок большего размера.

int *tmp = realloc(a, 2 * sizeof(*a));  /* down from more */
if (tmp) a = tmp;

Избегайте переполнения в математических вычислениях

При большом значении ёмкости выражение cap * sizeof(*a) может вызвать переполнение типа size_t и превратиться в очень маленькое число.

Для огромных массивов проверяйте умножение на переполнение или используйте reallocarray в системах, где он доступен.

if (cap > SIZE_MAX / sizeof(*a)) { /* overflow */ return 1; }
int *tmp = realloc(a, cap * sizeof(*a));

Быстрая проверка

Проверьте, насколько хорошо Вы поняли работу realloc.

Повторение

realloc изменяет размер блока в куче и может переместить его, поэтому всегда используйте возвращённый указатель.

Присваивайте результат временной переменной, чтобы при ошибке не потерять исходный блок. Для ускорения увеличивайте размер вдвое, инициализируйте новые элементы и помните: realloc(NULL, n) эквивалентен malloc. Далее Вы обернёте эту логику в переиспользуемый тип вектора.

Часто задаваемые вопросы

Урок «Изменение размера с realloc» бесплатный?

Да — полный текст урока «Изменение размера с realloc» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C Academy, подпишись на CoddyKit PRO. Курс C Academy содержит 4 уроков всего.

Чему я научусь в уроке «Изменение размера с realloc»?

Изменяйте размер динамического массива. Ты практикуешь C Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать C Academy?

Предыдущий опыт не требуется. C Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «Изменение размера с realloc»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке C Academy?

Да. Каждый урок C Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Выделение массива
  2. Изменение размера с realloc
  3. Многоразовый тип вектора
  4. Освобождение памяти и предотвращение утечек
← Назад к C Academy