Использование 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
'\0' NULL
A(код: 65) '\0' NULL
Итерация 2
A(код: 65) B(код: 66) '\0' NULL
Итерация 3
A(код: 65) B(код: 66) C(код: 67) '\0' NULL
...

Рис. 1

Что видно из рис.1, на первой итерации realloc() выделил два символа в текстовом блоке динамической памяти, а уже на последующих итерациях ему потребовалось выделять лишь один под текстовый символ, так как память под символ конца строки ('\0') была уже выделена ранее.

К оглавлению