0Pricing
C Academy · Урок

Многоразовый тип вектора

Объедините размер и вместимость.

«Многоразовый тип вектора» — бесплатный урок 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 — локальная установка не требуется.

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

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