Очень часто возникают задачи обработки массивов данных, размерность которых заранее неизвестна. В этом случае возможно использование одного из двух подходов:
- выделение памяти под статический массив, содержащий максимально возможное число элементов, однако в этом случае память расходуется не рационально;
- динамическое выделение памяти для хранение массива данных.
Для использования функций динамического выделения памяти необходимо описать указатель, представляющий собой начальный адрес хранения элементов массива.
Начальный адрес статического массива определяется компилятором в момент его объявления и не может быть изменен.
Для динамического массива начальный адрес присваивается объявленному указателю на массив в процессе выполнения программы.
Стандартные функции динамического выделения памяти
Функции динамического выделения памяти находят в оперативной памяти непрерывный участок требуемой длины и возвращают начальный адрес этого участка.
Функции динамического распределения памяти:
void* calloc(ЧислоЭлементов, РазмерЭлементаВБайтах);
Для использования функций динамического распределения памяти необходимо подключение библиотеки <malloc.h>:
Функция malloc()
определена в заголовочном файле stdlib.h
, она используется для инициализации указателей необходимым объемом памяти. Память выделяется из сектора оперативной памяти доступного для любых программ, выполняемых на данной машине. Аргументом функции malloc()
является количество байт памяти, которую необходимо выделить, возвращает функция — указатель на выделенный блок в памяти. Функция malloc() работает также как и любая другая функция, ничего нового. Если память выделить не удалось, то функция возвращает NULL. Так как malloc возвращает указатель типа void, то его необходимо явно приводить к нужному нам типу.
Используя указатель, можно работать с выделенной памятью как с массивом.
Функция free
освобождает место в памяти. Блок памяти, ранее выделенный с помощью вызова malloc
, calloc
или realloc
освобождается. То есть освобожденная память может дальше использоваться программами или ОС.
Обратите внимание, что эта функция оставляет значение п
еременной
неизменным, следовательно, он по-прежнему указывает на тот же блок памяти, а не на нулевой указатель. Поэтому, после освобождения памяти, хорошей практикой является сброс указателя в нуль, то есть присвоить *ptrVar = 0
. Если указателю присвоить 0, указатель становится нулевым, другими словами, он уже никуда не указывает. Всегда после высвобождения памяти, присваивайте указателю 0, в противном случае, даже после высвобождения памяти, указатель все равно на неё указывает, а значит вы случайно можете нанести вред другим программам, которые, возможно будут использовать эту память, но вы даже ничего об этом не узнаете и будете думать, что программа работает корректно.