Многоразовый тип вектора
Объедините размер и вместимость.
«Многоразовый тип вектора» — бесплатный урок C Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C Academy содержит 4 уроков всего.
От разрозненного кода к типу
Передача указателя, количества элементов и ёмкости в виде трёх отдельных переменных чревата ошибками.
Давайте объединим их в одну struct: переиспользуемый динамический массив, который часто называют вектором. Он объединяет данные и служебную информацию.
Структура вектора
Вектору нужны три поля: указатель на данные, количество используемых элементов (len) и количество элементов, помещающихся до изменения размера (cap).
typedef struct {
int *data;
size_t len;
size_t cap;
} Vec;Инициализация вектора
Пустой вектор имеет указатель на данные NULL, а также нулевые длину и ёмкость. Небольшая функция инициализации делает намерение очевидным.
void vec_init(Vec *v) {
v->data = NULL;
v->len = 0;
v->cap = 0;
}Операция добавления
vec_push добавляет один элемент в конец. Если вектор заполнен, сначала ёмкость увеличивается вдвое.
При успехе функция возвращает 0, а при ошибке выделения памяти — -1, чтобы вызывающий код мог отреагировать.
int vec_push(Vec *v, int value) {
if (v->len == v->cap) {
size_t nc = v->cap ? v->cap * 2 : 4;
int *tmp = realloc(v->data, nc * sizeof(*v->data));
if (!tmp) return -1;
v->data = tmp;
v->cap = nc;
}
v->data[v->len++] = value;
return 0;
}Чтение элементов
Поскольку len хранит количество используемых элементов, перебирайте их от 0 до len - 1. Ёмкость может быть больше, но дополнительные позиции пока не относятся к Вашим данным.
for (size_t i = 0; i < v->len; i++)
printf("%d\n", v->data[i]);Освобождение вектора
Вектор владеет буфером в куче, поэтому ему нужна соответствующая функция очистки. После освобождения сбросьте поля, чтобы структуру нельзя было использовать неправильно.
void vec_free(Vec *v) {
free(v->data);
v->data = NULL;
v->len = v->cap = 0;
}Собираем всё вместе
Эта полная программа создаёт вектор, добавляет пять значений, выводит их, а затем корректно освобождает память.
#include <stdio.h>
#include <stdlib.h>
typedef struct { int *data; size_t len, cap; } Vec;
int vec_push(Vec *v, int value) {
if (v->len == v->cap) {
size_t nc = v->cap ? v->cap * 2 : 4;
int *tmp = realloc(v->data, nc * sizeof(*v->data));
if (!tmp) return -1;
v->data = tmp; v->cap = nc;
}
v->data[v->len++] = value;
return 0;
}
int main(void) {
Vec v = {0};
for (int i = 0; i < 5; i++) vec_push(&v, i * 10);
for (size_t i = 0; i < v.len; i++) printf("%d\n", v.data[i]);
free(v.data);
return 0;
}Инициализация нулями с помощью {0}
Запись Vec v = {0}; устанавливает все поля в ноль, включая указатель на данные, равный NULL.
Это удобное сокращение: после него вектор готов к использованию vec_push без вызова отдельной функции инициализации.
Vec v = {0}; /* data=NULL, len=0, cap=0 */
vec_push(&v, 42);Безопасная вспомогательная функция get
Обращение по индексу за пределами len — это ошибка. Небольшая функция доступа может проверить границы и сообщить об ошибке, пожертвовав небольшой частью скорости ради безопасности.
int vec_get(const Vec *v, size_t i, int *out) {
if (i >= v->len) return -1; /* out of range */
*out = v->data[i];
return 0;
}Зачем хранить len и cap отдельно
cap — это объём выделенной памяти, а len — фактическое количество используемых элементов.
Запас ёмкости позволяет большинству операций добавления обходиться без вызова realloc. Именно это разделение делает вектор одновременно быстрым и гибким.
Обобщение типа
Этот вектор хранит значения типа int. Чтобы хранить другие типы, можно изменить тип элементов или использовать void * вместе с размером элемента.
Шаблон — инициализация, добавление, освобождение — остаётся тем же независимо от хранимых данных.
typedef struct {
double *data;
size_t len, cap;
} DVec; /* same shape, different element type */Быстрая проверка
Проверьте, насколько хорошо Вы поняли тип вектора.
Повторение
Вектор объединяет указатель на данные, len и cap в одну структуру.
vec_push удваивает ёмкость при заполнении, vec_free освобождает буфер и сбрасывает поля, а {0} корректно инициализирует структуру. Этот переиспользуемый шаблон удобнее, чем управление разрозненными переменными. Далее: правильное освобождение памяти и предотвращение утечек.
Часто задаваемые вопросы
Урок «Многоразовый тип вектора» бесплатный?
Да — полный текст урока «Многоразовый тип вектора» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C Academy, подпишись на CoddyKit PRO. Курс C Academy содержит 4 уроков всего.
Чему я научусь в уроке «Многоразовый тип вектора»?
Объедините размер и вместимость. Ты практикуешь C Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать C Academy?
Предыдущий опыт не требуется. C Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «Многоразовый тип вектора»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке C Academy?
Да. Каждый урок C Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Выделение массива
- Изменение размера с realloc
- Многоразовый тип вектора
- Освобождение памяти и предотвращение утечек