malloc против calloc: ключевые отличия с практическими примерами
Что такое динамическое выделение памяти?
Динамическое выделение позволяет программе запрашивать и освобождать память во время выполнения. В C стандартная библиотека предоставляет четыре функции: malloc(), calloc(), realloc() и free() — все объявлены в stdlib.h.
malloc(): выделение одиночного блока
malloc() (memory allocation) резервирует непрерывный блок байтов и возвращает указатель на первый байт. Содержимое неинициализировано — там остаются случайные биты.
Типичное использование:
int *p = (int *)malloc(n * sizeof(int));
При неудаче возвращает NULL.
calloc(): выделение нескольких обнулённых блоков
calloc() (contiguous allocation) принимает два аргумента: количество элементов и размер каждого. Выделяет память под все элементы и автоматически обнуляет каждый байт — идеально для массивов или структур, требующих чистого старта.
Типичное использование:
int *p = (int *)calloc(n, sizeof(int));
При неудаче возвращает NULL.
Когда что использовать
- malloc() — когда нужен одиночный блок и вы сами инициализируете память. Чуть быстрее, так как пропускает обнуление.
- calloc() — когда нужен массив или структура, которые должны начинаться с нулей. Автоматическая инициализация защищает от случайного использования мусорных значений.
Синтаксис
malloc()
void *malloc(size_t size);
calloc()
void *calloc(size_t num, size_t size);
Практические примеры кода
Пример 1: malloc() для 15 целых
#include <stdlib.h>
#include <stdio.h>
int main(void) {
int *ptr = malloc(15 * sizeof(*ptr));
if (!ptr) {
perror("malloc failed");
return EXIT_FAILURE;
}
ptr[5] = 480; // 6-й элемент (0-индексация)
printf("Value of the 6th integer is %d\n", ptr[5]);
free(ptr);
return EXIT_SUCCESS;
}
Вывод: Value of the 6th integer is 480
Пример 2: calloc() для вычисления суммы
#include <stdlib.h>
#include <stdio.h>
int main(void) {
int *ptr = calloc(10, sizeof(int));
if (!ptr) {
perror("calloc failed");
return EXIT_FAILURE;
}
int sum = 0;
for (int i = 0; i < 10; ++i) {
ptr[i] = i; // инициализация избыточна, но показана для ясности
sum += ptr[i];
}
printf("Sum = %d\n", sum);
free(ptr);
return EXIT_SUCCESS;
}
Вывод: Sum = 45
Побочное сравнение
| Характеристика | malloc() | calloc() |
|---|---|---|
| Количество параметров | 1 (размер) | 2 (количество, размер) |
| Состояние памяти после выделения | Неинициализирована (мусор) | Обнулена |
| Типичный сценарий | Одиночный блок, ручная инициализация | Массивы/структуры, требующие чистого старта |
| Производительность | Быстрее (нет обнуления) | Медленнее (накладные расходы на обнуление) |
| Безопасность | Риск использования мусора | Меньше рисков благодаря автообнулению |
| Возврат при ошибке | NULL | NULL |
| Заголовочный файл | stdlib.h | stdlib.h |
Резюме
- Используйте
malloc()для одиночного блока с ручной инициализацией — небольшой прирост скорости. - Используйте
calloc()когда нужна обнулённая память, особенно для массивов или структур — избегайте тонких багов. - Обе функции возвращают
NULLпри неудаче; всегда проверяйте перед разыменованием. - Не забывайте освобождать память через
free(), чтобы избежать утечек.
Язык C
- Выражения, операторы и блоки в C#: подробное руководство с примерами
- Цикл do-while в C++: синтаксис, примеры и вложенные циклы
- Указатели в C++: концепции, примеры и практические применения
- Тип данных char в C++: объявление, ASCII и методы преобразования
- Перегрузка операторов в C++: практическое руководство с примерами кода
- Функции в C++: подробное объяснение с практическими примерами кода
- Коллекции в C#: практическое руководство с реальными примерами
- Циклы while и do-while: наглядное сравнение с практическими примерами
- calloc() в C: выделение обнулённой памяти и практический пример
- Мастерство метода str.count() в Python: как подсчитывать символы и подстроки с примерами