Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
http.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
1.34 Mб
Скачать

Динамическое выделение и указатели

У всех откомпилированных программ С при размещении в памяти можно выделить четыре области: код программы, глобальные данные, стек и куча. Куча - это область свободной памяти, управляемая функциями динамического выделения malloc() и free().

Функция malloc() выделяет память и возвращает указатель на начало выделенного блока. Функция free() возвращает ранее выделенную память в кучу для повторного использования. Ниже показаны прототипы функций malloc() и free(): void *malloc(size_t число_байт); void free(void *p);

Обе функции используют заголовочный файл stdlib.h. Здесь число_число - это число требуемых байт. Если недостаточно свободной памяти для выполнения запроса, malloc() возвращает NULL. Тип size_t определен в stdlib.h и является беззнаковым целым типом, способным хранить размер памяти, выделяемой при одном вызове malloc(). Важно, что free() должна вызываться только с корректным, ранее выделенным указателем, иначе структура кучи может быть повреждена, что может привести к краху программы.

фрагмент кода, показанный ниже, выделяет 25 байт памяти: char *р; р = (char *) malloc(25);

После присвоения р указывает на первый из 25 выделенных байт. Оператор принудительного преобразования char* не нужен в С, но необходим в С++. В С, если не используется преобразование типов с malloc(), то тип указателя автоматически преобразуется к типу, аналогичному типу переменной, стоящей слева оператора присваивания. В С++ такое неявное преобразование указателей не разрешается. Хотя в С это и не нужно, использование преобразований типов позволяет программам С компилироваться с помощью С++. Ниже показан фрагмент кода, выделяющий место для 50 целых чисел. Он использует sizeof для обеспечения переносимости: int *р; р = (int *) malloc(50*sizeof (int));

Поскольку куча не бесконечна, при выделении памяти необходимо проверять значение, возвращаемое malloc(), чтобы убедиться, что оно не нулевое. Использование нулевого указателя может привести к зависанию компьютера. Ниже показан корректный способ выделения памяти и тестирования на корректность указателя: int *р; if ((р = (int *) malloc (100) )==NULL) { printf("Out of memory.\n"); exit (1); }

Макроопределение NULL находится в stdlib.h. Конечно, можно использовать другой обработчик ошибок вместо exit(). Самое главное - не использовать указатель р, если он нулевой.

Следует включать заголовочный файл stdlib.h в начало всех файлов, использующих функции malloc() и free(), поскольку он содержит их прототипы.

Указатели на константы

Модификатор const может использоваться для защиты объекта от возможного изменения со стороны функции. То есть, когда указатель передается в функцию, функция может модифицировать оригинал переменной, на которую указывает указатель. Если указатель определен как const, то функция не сможет модифицировать объект. Например, функция sp_to_dash() в следующей программе выводит дефис вместо каждого пробела в передаваемой строке. То есть строка «this is а test» будет напечатана как «this-is-a-test». Использование const при объявлении параметра гарантирует, что код функции не может модифицировать объект, на который указывает параметр. #include <stdio.h> void sp_to_dash(const char *str); int main(void) { sp_to_dash ("this is a test"); return 0; } void sp_to_dash (const char *str) { while(*str) { if(*str == ' ') printf ("%c", '-'); else printf("%c", *str); str++; } } Если написать sp_to_dash() таким образом, чтобы она модифицировала строку, то она не будет компилироваться. Например, если написать sp_to_dash() /* Это неверно */ void sp_to_dash (const char *str) { while(*str) { if(*str == ' ') *str = '-'; /* невозможно выполнить */ printf("%c", *str); str++; } } то возникнет ошибка времени компиляции.

Многие функции в стандартных библиотеках используют const при объявлении своих параметров. Это гарантирует сохранность объектов, на которые указывают параметры.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]