0Pricing
C Academy · Урок

calloc и realloc

Обнуляйте и изменяйте размер памяти

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

Помимо malloc

Помимо malloc, стандартная библиотека предлагает calloc для выделения обнулённой памяти и realloc для изменения размера существующего блока.

Обе функции находятся в <stdlib.h>.

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

int main(void) {
    int *p = calloc(3, sizeof(int));
    printf("%d %d %d\n", p[0], p[1], p[2]);
    free(p);
    return 0;
}

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

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

Это удобно, когда требуется чистое начальное состояние.

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

int main(void) {
    int *a = calloc(5, sizeof(int));
    int sum = 0;
    for (int i = 0; i < 5; i++) sum += a[i];
    printf("sum of zeroed array = %d\n", sum);
    free(a);
    return 0;
}

У calloc два аргумента

В отличие от malloc, calloc принимает количество элементов и размер элемента по отдельности.

Кроме того, функция защищает от переполнения при умножении количества элементов на их размер.

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

int main(void) {
    double *d = calloc(4, sizeof(double));
    d[2] = 1.5;
    printf("%f %f\n", d[0], d[2]);
    free(d);
    return 0;
}

malloc и calloc

Используйте malloc, если всё равно перезапишете каждый байт, а calloc — если рассчитываете, что память изначально заполнена нулями.

calloc работает немного медленнее из-за обнуления памяти.

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

int main(void) {
    int *m = malloc(2 * sizeof(int));
    int *c = calloc(2, sizeof(int));
    m[0] = 5; m[1] = 6;
    printf("malloc: %d %d\n", m[0], m[1]);
    printf("calloc: %d %d\n", c[0], c[1]);
    free(m); free(c);
    return 0;
}

Увеличение с помощью realloc

realloc(ptr, newsize) изменяет размер блока, сохраняя его содержимое до меньшего из старого и нового размеров.

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

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

realloc может переместить блок

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

Всегда присваивайте результат обратно указателю и никогда не продолжайте использовать старый указатель.

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

int main(void) {
    int *a = malloc(sizeof(int));
    a[0] = 42;
    int *bigger = realloc(a, 100 * sizeof(int));
    printf("first element still %d\n", bigger[0]);
    free(bigger);
    return 0;
}

Безопасный шаблон realloc

Если realloc завершается ошибкой, он возвращает NULL, но оставляет исходный блок нетронутым.

Сначала присвойте результат временной переменной, чтобы не потерять старый указатель в случае ошибки.

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

int main(void) {
    int *a = malloc(2 * sizeof(int));
    int *tmp = realloc(a, 8 * sizeof(int));
    if (tmp == NULL) {
        free(a);
        return 1;
    }
    a = tmp;
    a[7] = 99;
    printf("%d\n", a[7]);
    free(a);
    return 0;
}

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

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

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

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

Растущий буфер

Распространённый приём заключается в удвоении ёмкости, когда массив заполняется, что позволяет распределить стоимость увеличения размера.

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

int main(void) {
    int cap = 2, len = 0;
    int *a = malloc(cap * sizeof(int));
    for (int v = 0; v < 5; v++) {
        if (len == cap) {
            cap *= 2;
            a = realloc(a, cap * sizeof(int));
        }
        a[len++] = v;
    }
    printf("len=%d cap=%d last=%d\n", len, cap, a[len-1]);
    free(a);
    return 0;
}

realloc с NULL

realloc(NULL, size) работает в точности как malloc(size).

Благодаря этому функция увеличения буфера может одинаково обрабатывать самое первое выделение памяти.

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

int main(void) {
    int *a = realloc(NULL, 3 * sizeof(int));
    a[0] = 7;
    printf("%d\n", a[0]);
    free(a);
    return 0;
}

Сочетание функций

Можно начать с calloc, чтобы получить обнулённый буфер, а затем увеличить его с помощью realloc. Новые байты после увеличения не обнуляются.

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

int main(void) {
    int *a = calloc(2, sizeof(int));
    a = realloc(a, 4 * sizeof(int));
    a[2] = 0; a[3] = 0;
    printf("%d %d %d %d\n", a[0], a[1], a[2], a[3]);
    free(a);
    return 0;
}

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

Проверьте свои знания о calloc и realloc.

Повторение

Вы изучили ещё два инструмента выделения памяти:

  • calloc(count, size) выделяет обнулённую память и защищает от переполнения при умножении.
  • realloc(ptr, newsize) изменяет размер блока и может переместить его.
  • Всегда присваивайте результат realloc временной переменной, чтобы избежать утечки в случае ошибки.
  • realloc(NULL, size) работает как malloc.

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

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

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

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

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

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

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

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

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

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

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

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

  1. malloc и free
  2. calloc и realloc
  3. Утечки памяти
  4. Висячие указатели
← Назад к C Academy