Рубрики

Хранение для струнных в C

В C на строку можно ссылаться либо используя символьный указатель, либо как символьный массив.

Строки как символьные массивы

char str[4] = "GfG"; / * Один дополнительный для терминатора строки * /

/* ИЛИ */

char str[4] = {‘G’, ‘f’, ‘G’, '\0'}; / * '/ 0' является ограничителем строки * /

Когда строки объявляются как символьные массивы, они сохраняются, как и другие типы массивов в C. Например, если str [] является автоматической переменной, тогда строка сохраняется в сегменте стека, если это глобальная или статическая переменная, которая затем сохраняется в сегменте данных , и т.д.

Строки с использованием указателей символов
Использование строк указателей символов может быть сохранено двумя способами:

1) Только для чтения строка в общем сегменте.
Когда строковое значение напрямую назначается указателю, в большинстве компиляторов оно сохраняется в блоке только для чтения (обычно в сегменте данных), который используется совместно для функций.

char *str  =  "GfG";  

В приведенной выше строке «GfG» хранится в общем доступном только для чтения месте, но указатель str хранится в памяти для чтения и записи. Вы можете изменить str, чтобы указать на что-то другое, но не можете изменить значение в данный момент str. Так что этот тип строки следует использовать только тогда, когда мы не хотим изменять строку на более позднем этапе в программе.

2) Динамически распределяется в сегменте кучи.
Строки хранятся, как и другие динамически размещаемые объекты в C, и могут быть разделены между функциями.

char *str;

int size = 4; / * один дополнительный за '/ 0' * /

str = (char *)malloc(sizeof(char)*size);

*(str+0) = 'G'

*(str+1) = 'f';  

*(str+2) = 'G';  

*(str+3) = '\0';  

Давайте рассмотрим несколько примеров, чтобы лучше понять вышеуказанные способы хранения строк.

Пример 1 (Попробуйте изменить строку)
Приведенная ниже программа может аварийно завершить работу (выдает ошибку ошибки сегментации), поскольку строка * (str + 1) = 'n' пытается записать только для чтения память.

int main()

{

 char *str; 

 str = "GfG";     / * Хранится в доступной только для чтения части сегмента данных * /

 *(str+1) = 'n'; / * Проблема: попытка изменить постоянную память * /

 getchar();

 return 0;

}

Программа ниже прекрасно работает, так как str [] хранится в сегменте стека, доступном для записи.

int main()

{

 char str[] = "GfG"/ * Хранится в сегменте стека, как и другие авто переменные * /

 *(str+1) = 'n';   / * Нет проблем: строка теперь GnG * /

 getchar();

 return 0;

}

Программа ниже также прекрасно работает, так как данные на str хранятся в доступном для записи сегменте кучи.

int main()

{

  int size = 4;

  

  / * Хранится в сегменте кучи, как и другие динамически распределяемые вещи * /

  char *str = (char *)malloc(sizeof(char)*size);

  *(str+0) = 'G'

  *(str+1) = 'f';  

  *(str+2) = 'G';    

  *(str+3) = '\0';  

  *(str+1) = 'n'/ * Нет проблем: строка теперь GnG * /

   getchar();

   return 0;

}     

Пример 2 (Попробуйте вернуть строку из функции)
Приведенная ниже программа работает отлично, так как строка хранится в общем сегменте, а сохраненные данные остаются там даже после возврата getString ()

char *getString()

{

  char *str = "GfG"; / * Хранится в доступной только для чтения части общего сегмента * /

  

  / * Нет проблем: остается по адресу str после возврата getString () * /

  return str;  

}     

  

int main()

{

  printf("%s", getString());  

  getchar();

  return 0;

}

Приведенная ниже программа также прекрасно работает, поскольку строка хранится в сегменте кучи, а данные, хранящиеся в сегменте кучи, сохраняются даже после возврата getString ().

char *getString()

{

  int size = 4;

  char *str = (char *)malloc(sizeof(char)*size); / * Хранится в сегменте кучи * /

  *(str+0) = 'G'

  *(str+1) = 'f';  

  *(str+2) = 'G';

  *(str+3) = '\0';  

    

  / * Нет проблем: строка остается в str после возврата getString () * /    

  return str;  

}     

int main()

{

  printf("%s", getString());  

  getchar();

  return 0;

}

Но нижеприведенная программа может напечатать некоторые ненужные данные, так как строка хранится в стековом фрейме функции getString (), а данные могут отсутствовать после возврата getString ().

char *getString()

{

  char str[] = "GfG"; / * Хранится в сегменте стека * /

  

  / * Проблема: строка может отсутствовать после возврата getSting () * /

  return str; 

}     

int main()

{

  printf("%s", getString());  

  getchar();

  return 0;

}

Пожалуйста, напишите комментарии, если вы обнаружите что-то неправильное в приведенной выше статье, или вы хотите поделиться дополнительной информацией о хранении строк

Рекомендуемые посты:

Хранение для струнных в C

0.00 (0%) 0 votes