Выделение памяти с помощью calloc()
Часть раздела Logic & Flow путешествия по C на Coddy — урок 36 из 63.
В то время как malloc() является наиболее распространенной функцией для динамического выделения памяти, C предоставляет еще одну полезную альтернативу: calloc(). Функция calloc(), название которой расшифровывается как «contiguous allocation» (непрерывное выделение), предлагает удобный способ выделения памяти для массивов с важным дополнительным преимуществом.
В отличие от malloc(), которая принимает один аргумент (общее количество байт), calloc() принимает два аргумента: количество элементов, которые вы хотите выделить, и размер каждого элемента. Это делает её особенно интуитивно понятной при работе с массивами. Например:
#include <stdlib.h>
// Выделение памяти для 5 целых чисел с помощью calloc()
int *arr = (int*)calloc(5, sizeof(int));
// Это эквивалентно: malloc(5 * sizeof(int))Ключевое преимущество calloc() заключается в том, что она автоматически инициализирует всю выделенную память нулем. При использовании malloc() выделенная память содержит любые случайные значения, которые были сохранены там ранее, но calloc() гарантирует, что каждый байт будет установлен в ноль. Это означает, что все целые числа будут равны 0, все числа с плавающей запятой — 0.0, а все указатели будут иметь значение NULL.
Как и malloc(), calloc() возвращает указатель на выделенную память или NULL, если выделение памяти завершилось неудачей, поэтому вам всегда следует проверять результат выделения и не забывать free() память, когда вы закончите её использовать.
Задание
ЛегкоНапишите программу на языке C, которая демонстрирует использование calloc() для динамического выделения памяти с автоматической инициализацией нулями. Ваша программа должна:
- Считать целое число
sizeот пользователя, представляющее количество целых чисел для выделения памяти - Использовать
calloc()для динамического выделения памяти под массив изsizeцелых чисел - Проверить, было ли выделение памяти успешным — если оно не удалось, вывести
Memory allocation failed!и завершить программу - Если выделение памяти прошло успешно, вывести
Memory allocated and initialized to zero! - Вывести все начальные значения в массиве, чтобы продемонстрировать, что они равны нулю, в формате:
Initial values: [value1] [value2] [value3] ... - Считать
sizeцелых чисел от пользователя и сохранить их в выделенном массиве - Вывести все обновленные значения в формате:
Updated values: [value1] [value2] [value3] ... - Вычислить и вывести сумму всех значений в формате:
Sum: [value] - Использовать
free()для освобождения памяти - Вывести
Memory freed!для подтверждения очистки
Не забудьте включить заголовочный файл <stdlib.h> для использования calloc() и free(). Эта задача демонстрирует ключевое преимущество calloc() перед malloc(): автоматическую инициализацию всей выделенной памяти нулями.
Например, если входные данные:
3
10 20 30Ваш вывод должен быть:
Memory allocated and initialized to zero!
Initial values: 0 0 0
Updated values: 10 20 30
Sum: 60
Memory freed!Эта задача подчеркивает, как calloc() обеспечивает чистое, предсказуемое начальное состояние для ваших динамически выделенных массивов, устраняя непредсказуемые «мусорные» значения, которые может оставить malloc().
Попробуйте сами
#include <stdio.h>
#include <stdlib.h>
int main() {
int size;
// Считать размер массива
scanf("%d", &size);
// TODO: Напишите ваш код ниже
// Используйте calloc() для выделения памяти под массив
// Проверьте, было ли выделение памяти успешным
// Выведите начальные значения (должны быть нулевыми)
// Считайте и сохраните входные значения
// Выведите обновленные значения
// Вычислите и выведите сумму
// Освободите выделенную память
return 0;
}В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Logic & Flow
1Основы указателей
Что такое указатель?Объявление указателейОператор взятия адреса (&)Оператор разыменования (*)Указатели NULLИтоги: Основы указателей4Проект: Простая текстовая утилита
Обзор проектаПодсчет символов2Указатели и массивы
Имена массивов как указателиЭлементы массива — указателиАрифметика указателейСравнение указателейИтоги: Обход массива через указатели5Указатели и функции
Передача по значениюПередача указателей в функцииИзменение переменных через указателиКлассический пример: SwapПередача массивов в функцииИтоги: указатели как аргументы функций8Структуры и указатели
Указатели на структурыОператор «стрелка» (->)Передача структур по значениюПередача указателей на структурыДинамическое выделение памяти для структурИтоги: Изменение структур через указатели11Итоговые задачи на повторение
Повторение: динамическая конкатенация строкПовторение: массив структурПовторение: счетчик частоты слов3Символьные массивы и строки
Строки как массивы charНуль-терминаторВвод строк с помощью scanfИспользование strlen()Использование strcpy()Использование strcat()Использование strcmp()Итоги: основные строковые функции6Управление памятью
Стек против кучиДинамическое выделение — malloc()Использование sizeof() для выделения памятиПроверка ошибок выделения памятиОсвобождение памяти с помощью free()Выделение памяти с помощью calloc()Итоги: Динамический массив