Использование 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') была уже выделена ранее.