Указатель на константную строку в C - PullRequest
12 голосов
/ 29 июня 2011
char *p = "string"; //creates pointer to constant string

char p[] = "string"; //just an array with "string"

Я просто немного озадачен, почему в первом примере создается указатель на постоянную строку? Разве это не должен быть просто указатель, ссылающийся на место в памяти с «строкой»?

Ответы [ 4 ]

22 голосов
/ 29 июня 2011

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

Во второмВ этом случае фактическая память выделяется и инициализируется в стеке во время выполнения (или в соответствующем разделе процесса при запуске программы, если это не локальная переменная), поэтому изменение памяти в порядке.

Первый случай можетПроиллюстрировать это следующим образом:

+---+           +---+---+---+---+---+---+---+
|   |   ---->   | s | t | r | i | n | g | \0|
+---+           +---+---+---+---+---+---+---+
  p

В то время как второй случай:

+---+---+---+---+---+---+---+
| s | t | r | i | n | g | \0|
+---+---+---+---+---+---+---+
              p

Эти два объявления имеют существенную разницу, хотя вы, возможно, слышали, что они одинаковы от низкогокниги по программированию качества C.

Первый - это указатель типа char *, а второй - массив типа char [].Идентификаторы массива распадаются на указатель в некоторых контекстах, но это не делает их указателями.

Указатель - это просто адрес, а массив - это "все" - в первомcase sizeof(p) возвращает размер указателя (обычно 4 или 8 в зависимости от целевой машины), а во втором случае - 7 * sizeof(char), длину фактической строки.

15 голосов
/ 29 июня 2011

К сожалению, это допустимо в C (и в C ++ 03 для совместимости) Но любая попытка изменить строковый литерал через указатель приведет к неопределенному поведению. Поэтому лучше всегда присваивать строковый литерал в const char*

const char * cp = "Hello"; //OK
char* p = "Hello"; //OK in C and C++03 (unfortunately), Illegal in C++11
cp[0] = 'Y'; //Compile-time error, good
p[0] = 'Y'; //no compiler error, undefined behavior
3 голосов
/ 29 июня 2011

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

Второй создает массив и копирует в него символов.Запись в этот массив приведет к записи в какое-то место в вашем стеке и будет абсолютно законной.

1 голос
/ 05 мая 2017

В первом случае «строка» может храниться в области процесса, доступной только для чтения, поэтому попытка изменить память, на которую указывает p, приведет к неопределенному поведению.

Это может быть подтверждено повторным запуском вышеуказанной строки кодов.

char *p="string";

вы заметите, что содержание p (то есть адрес "строки") остается постоянным.

char p[] = "string"; 

для этой памяти выделяется, следовательно, каждый раз, когда вы запускаете содержимое p изменений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...