Язык программирования Си (Ритчи, Керниган) - страница 83

выдает нуль. Функция afree(p) просто устанавливает allocp в значение p, если оно не выходит за пределы массива allocbuf.

Перед вызовом allос:

После вызова alloc:

>#define ALLOCSIZE 10000 /* размер доступного пространства */


>static char allocbuf[ALLOCSIZE]; /* память для alloc */

>static char *allocp = allocbuf; /* указатель на своб. место */


>char *alloc(int n) /* возвращает указатель на n символов */

>{

> if (allocbuf + ALLOCSIZE - allocp ›= n) {

> allocp += n; /* пространство есть */

> return allocp - n; /* старое p */

>} else /* пространства нет */

> return 0;

>}


>void afree(char *p) /* освобождает память, на которую указывает p */

>{

> if (р ›= allocbuf && p ‹ allocbuf + ALLOCSIZE)

> allocp = p;

>}

В общем случае указатель, как и любую другую переменную, можно инициализировать, но только такими осмысленными для него значениями, как нуль или выражение, приводящее к адресу ранее определенных данных соответствующего типа. Объявление

>static char *allocp = allocbuf;

определяет allocp как указатель на char и инициализирует его адресом массива allocbuf, поскольку перед началом работы программы массив allocbuf пуст. Указанное объявление могло бы иметь и такой вид:

>static char *allocp = &allocbuf[0];

поскольку имя массива и есть адрес его нулевого элемента. Проверка

>if (allocbuf + ALLOCSIZE - allocp ›= n) {/* годится */

контролирует, достаточно ли пространства, чтобы удовлетворить запрос на n символов. Если памяти достаточно, то новое значение для allocp должно указывать не далее чем на следующую позицию за последним элементом allocbuf. При выполнении этого требования alloc выдает указатель на начало выделенного блока символов (обратите внимание на объявление типа самой функции). Если требование не выполняется, функция alloc должна выдать какой-то сигнал о том, что памяти не хватает. Си гарантирует, что нуль никогда не будет правильным адресом для данных, поэтому мы будем использовать его в качестве признака аварийного события, в нашем случае нехватки памяти.

Указатели и целые не являются взаимозаменяемыми объектами. Константа нуль - единственное исключение из этого правила: ее можно присвоить указателю, и указатель можно сравнить с нулевой константой. Чтобы показать, что нуль - это специальное значение для указателя, вместо цифры нуль, как правило, записывают NULL - константу, определенную в файле ‹stdio.h› (I.B.: вообще-то эта константа определена в ‹stddef.h› или ‹string.h›). С этого момента и мы будем ею пользоваться. Проверки

>if (allocbuf + ALLOCSIZE - allocp ›= n) {/* годится */

и

>if (p ›= allocbuf && p ‹ allocbuf + ALLOCSIZE)