Использование realloc() в GNU C
Позволяет изменять ( увеличивать ) размер выделенного ранее блока динамической памяти, как показано в листинге 1.
|
Листинг 1
/* Функция mtext_length_get() подсчитывает и возвращает число записанных выделенных ранее realloc() символов,
исключая специальный символ конца строки '\0' */
static __inline__ int mtext_length_get ( const char *text_p )
{
char *go = (char *)text_p;
for ( ; go && *go && *go != '\0'; go++ )
;
return (int)(go-text_p);
}
int main ( int argc, char** argv )
{
int mlength; /* Кол-во найденных текстовых символов в динамической памяти */
char *text_p = NULL, /* Указатель на динамически изменяемый блок памяти. При этом, когда указатель равен NULL,*/
/* realloc() выделит память заданного размера подобно malloc(). */
symbol = 65; /* Первый записываемый символ 'A' */
/* Для наглядности увеличиваем каждый раз на один символ текстовый блок, выделенный в памяти */
for ( symbol = 65 ; symbol < 91; symbol++ ) { /* Пишем символы ASCII от 'A' по 'Z' */
mlength = mtext_length_get(text_p);
/* mtext_length_get() возвращает только количество текстовых символов, записанных в динамической памяти,
поэтому нам нужно размер ранее выделенной памяти увеличить на один символ, а затем выделить место под
специальный символ конца строки. */
text_p = realloc ( text_p, ++length + 1 ); /* Поэтому фактически увеличиваем память на один символ */
if ( text_p == NULL ) return EXIT_FAILURE; /* Завершаемся с отказом, потому что увеличить память невозможно*/
*(text_p+mlength-1) = symbol; /* Меняем символ конца строки на текстовый */
*(text_p+mlength) = '\0'; /* А в новую выделенную позицию записываем символ конца строки,
нужный для определения её длинны mtext_length_get()*/
}
/* Печатаем результат*/
mlength = mtext_length_get(text_p);
fprintf(stdout,"Total %d symbols into text string: \"%s\"\n", mlength,
mlength ? text_p : "(empty)" );
/* Освобождаем выделенную память */
free(text_p);
return EXIT_SUCCESS; /* Завершаемся с признаком успешного завершения */
}
|
Как видно из листинга 1, функции mtext_length_get() отведена вспомогательная, но в тоже время важная роль в определении количества записанных текстовых символов, исключая специальный символ конца строки '\0'.
Основные и главные манипуляции с повторным выделением памяти происходят в функции main(), где в её единственном цикле вызывается realloc(). Для увеличения текстового блока на один символ выделяется новая ячейка динамической памяти, куда будет всегда записываться специальный символ конца строки, а в ранее выделенную ячейку будет помещен текстовый символ с кодом от 65 до 91. Исключение составляет запись начального символа с кодом 65, для которого одновременно выделяется сразу две ячейки в динамической памяти для записи текстового символа и конца строки, как показано на рис. 1 .
Итерация 1
|
||||||||||||||||||||||||||||||||||||
|
Рис. 1 |
Что видно из рис.1, на первой итерации realloc() выделил два символа в текстовом блоке динамической памяти, а уже на последующих итерациях ему потребовалось выделять лишь один под текстовый символ, так как память под символ конца строки ('\0') была уже выделена ранее.