Изменение размера с 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 — локальная установка не требуется.
Все уроки этого курса
- Выделение массива
- Изменение размера с realloc
- Многоразовый тип вектора
- Освобождение памяти и предотвращение утечек