0Pricing
C Academy · Урок

Выделение массива

Зарезервируйте память в куче.

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

Зачем нужны динамические массивы

Обычный массив имеет фиксированный размер, задаваемый во время компиляции. Но часто до запуска программы неизвестно, сколько элементов понадобится.

Динамические массивы решают эту проблему: во время выполнения Вы запрашиваете у операционной системы блок памяти с помощью malloc, а размер задаёте переменной.

Знакомство с malloc

malloc (выделение памяти) находится в <stdlib.h>. Ему передаётся количество байтов, а он возвращает указатель на этот блок или NULL, если операция не удалась.

Память выделяется в куче и остаётся занятой, пока Вы не освободите её.

int *p = malloc(10 * sizeof(int));

Определение размера с помощью sizeof

Никогда не задавайте количество байтов вручную. Используйте sizeof, чтобы код корректно работал на разных платформах.

Чтобы выделить место для n целых чисел, умножьте n на sizeof(int). Распространённая идиома — n * sizeof(*p), использующая собственный тип указателя.

int *p = malloc(n * sizeof(*p));

Всегда проверяйте NULL

Если системе не хватает памяти, malloc возвращает NULL. Разыменование нулевого указателя приводит к аварийному завершению программы.

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

int *p = malloc(n * sizeof(*p));
if (p == NULL) {
    fprintf(stderr, "out of memory\n");
    return 1;
}

Полное выделение памяти

Вот полноценная программа, которая выделяет место для 5 целых чисел, заполняет его и выводит их.

Обратите внимание на симметрию: malloc в начале и free в конце.

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

int main(void) {
    int n = 5;
    int *a = malloc(n * sizeof(*a));
    if (!a) return 1;
    for (int i = 0; i < n; i++) a[i] = i * i;
    for (int i = 0; i < n; i++) printf("%d\n", a[i]);
    free(a);
    return 0;
}

malloc не обнуляет память

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

Чтение до записи приводит к непредсказуемым значениям. Всегда присваивайте значение каждому элементу до его чтения.

int *a = malloc(3 * sizeof(*a));
/* a[0], a[1], a[2] hold garbage here */
a[0] = 10;

calloc обнуляет память за Вас

calloc(count, size) выделяет место для count элементов размером size байт и устанавливает каждый байт в ноль.

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

int *a = calloc(5, sizeof(*a));
/* every element is now 0 */

calloc в действии

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

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

int main(void) {
    int n = 4;
    int *a = calloc(n, sizeof(*a));
    if (!a) return 1;
    for (int i = 0; i < n; i++) printf("%d\n", a[i]);
    free(a);
    return 0;
}

Индексация блока

Указатель на блок в куче ведёт себя так же, как имя массива. С помощью a[i] можно читать и записывать любой элемент с индексом от 0 до n-1.

Внутри a[i] эквивалентно *(a + i).

int *a = malloc(3 * sizeof(*a));
a[0] = 1;
*(a + 1) = 2;   /* same as a[1] = 2 */
a[2] = 3;

Следите за границами

Если Вы выделили n элементов, допустимые индексы — от 0 до n-1. Запись в a[n] является неопределённым поведением.

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

int *a = malloc(3 * sizeof(*a));
a[2] = 99;   /* OK, last valid index */
/* a[3] = 0;  BUG: out of bounds */

Чтение размера во время выполнения

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

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

int main(void) {
    int n = 6;            /* could be scanf'd */
    long *a = malloc(n * sizeof(*a));
    if (!a) return 1;
    long sum = 0;
    for (int i = 0; i < n; i++) { a[i] = i + 1; sum += a[i]; }
    printf("%ld\n", sum);
    free(a);
    return 0;
}

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

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

Повторение

Динамический массив выделяют с помощью malloc(n * sizeof(*p)) или выделяют и заполняют нулями с помощью calloc(n, sizeof(*p)).

Всегда проверяйте NULL, помните, что malloc оставляет произвольные данные, используйте индексы от 0 до n-1 и сопровождайте каждое выделение вызовом free. Далее Вы научитесь изменять размер блока, сохраняя его данные.

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

Урок «Выделение массива» бесплатный?

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

Чему я научусь в уроке «Выделение массива»?

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

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

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

Сколько времени занимает урок «Выделение массива»?

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

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

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

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

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