В C, я могу инициализировать строку в объявлении указателя так же, как я могу инициализировать строку в объявлении массива char? - PullRequest
9 голосов
/ 29 октября 2010

Достигают ли эти две строки кода одинакового результата? Если бы у меня были эти строки в функции, хранится ли строка в стеке в обоих случаях? Есть ли веская причина, почему я должен использовать один над другим, кроме того, что нет необходимости объявлять нулевой терминатор в первой строке кода?

char  s[] = "string";
char* s   = "string\0";

Ответы [ 3 ]

24 голосов
/ 29 октября 2010

Нет, эти две строки не дают одинакового результата.

char s[] = "string" приводит к изменяемому массиву из 7 байтов, который изначально заполняется содержимым 's' 't' 'r' 'i' 'n' 'g' '\0' (все копируются во время выполнения из строкового литерала).

char *s = "string" приводит к указателю на некоторую только для чтения память, содержащую строковый литерал "string".

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


В обоих случаях нет необходимости указывать нулевой терминатор в строковом литерале. Об этом позаботится компилятор, когда встретится с закрытием ".

2 голосов
/ 29 октября 2010

Разница между этими двумя значениями:

char a[] = "string";
char* b = "string";

заключается в том, что a на самом деле является статическим массивом в стеке, а b - указателем на константу.Вы можете изменить содержимое a, но не b.

1 голос
/ 27 июня 2017

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

Концептуально, когда программа загружается в память, она имеет 3 области (сегмента):

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

В вашем случае переменная s[] является локальной переменной (массивом) в функции main(), которая инициализируется значением "string". Таким образом, он хранится в стеке и может быть изменен.

Переменная *s - это указатель, который указывает на адрес "string\0", константу, расположенную в сегменте кода. Будучи областью только для чтения, вы не можете изменять ее содержимое.

...