ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 13.12.2020
Просмотров: 4316
Скачиваний: 28
Глава 20. Стандартные определения <stddef.h>
281
int main(void)
{
printf("shift of 'salary' = %d bytes\n",
offsetof(struct emp, salary)); // печатает 24
return 0;
}
Г Л А В А
21
Стандартные функции
<stdlib.h>
21.1. Динамическое распределение
памяти
Под динамической памятью понимают память, которая выделяет-
ся программе из кучи. Динамическое распределение памяти за-
ключается в выделении программе по ее запросу памяти из кучи.
Если программа завершила работу с распределенной ей памятью,
то она должна освободить эту память, т. е. вернуть ее обратно в
кучу.
Для динамического распределения памяти в языке программиро-
вания С используются функции
malloc
,
calloc
и
realloc
. Ниже
приведены прототипы этих функций:
void* malloc(size_t size);
void* calloc(size_t n, size_t size);
void* realloc(void* ptr, size_t size);
Работают эти функции следующим образом.
Функция
malloc
выделяет программе память размером в
size
байт.
Функция
calloc
выделяет программе память размером в
(n*size)
байт, при этом выделенная память обнуляется.
Функция
realloc
перераспределяет память, на которую указывает
параметр
ptr
, до размера в
size
байтов. То есть программе вместо
Глава 21. Стандартные функции <stdlib.h>
283
старого распределяется новый блок памяти размером в
size
байт.
При этом содержимое старого блока, но не более чем
size
байт,
копируется в новый блок. Функция
realloc
используется глав-
ным образом для увеличения размера выделенной памяти.
Все эти функции в случае успеха возвращают указатель на выде-
ленную память, в случае неудачи —
NULL
.
Символическая константа
NULL
также определена в заголовочном
файле stdlib.h. Подробно эта константа была описана в
разд. 20.2
.
Параметры
size
и
n
этих функций имеют тип
size_t
, который
обычно является переопределением типа
unsigned int
. Опреде-
ление этого типа было дано в
разд. 20.1
. Тип
size_t
также опре-
делен и в заголовочном файле stdlib.h.
Тип
void*
называется
родовым указателем
, т. е. указателем на
"сырую" или "пустую" память. Впоследствии этот указатель при-
водится к указателю на нужный тип.
Для освобождения ранее выделенной программе памяти исполь-
зуется функция
free
, которая имеет следующий прототип:
void free(void* ptr);
Параметр
ptr
этой функции является указателем на освобождае-
мую память.
Сделаем два важных замечания. Во-первых, динамическую па-
мять нужно обязательно освобождать после ее использования.
Иначе остаются неиспользованные блоки памяти, которые назы-
ваются "мусором" или
утечками памяти
(memory leaks). Во-
вторых, динамическое выделение памяти используется только в
том случае, если программе заранее неизвестно, какой размер
памяти нужно отвести под данные. В противном случае нужно
использовать статическую память.
В листинге 21.1 приведена программа, которая динамически рас-
пределяет память под целое число.
Листинг 21.1. Динамическое распределение памяти
#include <stdio.h>
#include <stdlib.h>
Часть III. Стандартная библиотека языка программирования C
284
int main()
{
char c;
int* p = NULL;
/* Нажмите 'y', чтобы ввести целое число */
printf("Press 'y' to input integer: ");
scanf("%c", &c);
if (c == 'y')
{
/* выделяем память под целое число */
p = (int*)malloc(sizeof(int));
if (!p) /* если ошибка, то выходим из программы */
{
printf("Memory allocation failed.\n");
return 0;
}
printf("Input integer: "); /* Вводим целое число */
scanf("%d", p);
printf("You input integer: %d\n", *p);
free(p); /* освобождаем память */
}
else
printf("You don't want to input integer.\n");
return 0;
}
21.2. Динамические массивы
Массив, память под который выделяется во время исполнения
программы, называется
динамическим массивом
. Для того чтобы
динамически создать одномерный массив, нужно, во-первых,
объявить в программе указатель на тип, соответствующий типу
элементов этого массива, а во-вторых, выделить память под мас-
сив, используя одну из функций
malloc
или
calloc
.
В листинге 21.2 приведена программа, которая динамически соз-
дает одномерный целочисленный массив.
Глава 21. Стандартные функции <stdlib.h>
285
Листинг 21.2. Создание одномерного динамического массива
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *a, n; /* указатель на массив и размерность массива */
int i;
/* введите размерность массива */
printf("Input a size of an array: ");
scanf("%d", &n);
/* выделяем память под массив */
a = (int*)malloc(n * sizeof(int));
if (!a) /* если ошибка, то выходим из программы */
{
printf("Memory allocation failed.\n");
return 0;
}
/* вводим через пробел элементы массива */
printf("Input elements of the array: ");
for (i = 0; i < n; ++i)
scanf("%d", &a[i]);
/* что-то делаем с массивом */
printf("You input the array: ");
for (i = 0; i < n; ++i)
printf("%d ", a[i]);
printf("\n");
free(a); /* освобождаем выделенную память */
return 0;
}
В связи с этой программой заметим, что элементы одномерного
динамического массива можно ввести и следующим образом:
for (i = 0; i < n; ++i)
scanf("%d", a + i); /* a – адрес массива */