Массивы автоматически выделяют пространство, и их нельзя перемещать или изменять размер, в то время как указатели явно назначаются для указания на выделенное пространство и могут быть перемещены.
Имена массивов доступны только для чтения!
Вы можете (в общем случае) использовать выражение (*ptr)++
для изменения значения, на которое указывает ptr
, если ptr
является указателем, а не массивом (т.е. если ptr
объявлен как char* ptr
).
Однако в вашем первом примере:
char *ptr = "Hello!"
ptr
указывает на литеральную строку, а литеральные строки не разрешается изменять (они могут храниться в области памяти, не подлежащей записи, такой как ПЗУ или страницы памяти, помеченные как доступные только для чтения).
Во втором примере
char ptr[] = "Hello!";
объявляется массив, и инициализация фактически копирует данные литерала строки в выделенную память массива. Эта память массива является изменяемой, поэтому (*ptr)++
работает.
Примечание: во втором объявлении идентификатор ptr
сам по себе является идентификатором массива, а не указателем, и не является 'lvalue', поэтому его нельзя модифицировать (хотя в большинстве ситуаций он легко преобразуется в указатель). Например, выражение ++ptr
будет недействительным. Я думаю, что именно эту мысль пытаются донести некоторые другие ответы.
Указывая на строковый литерал, вы не должны объявлять символы как изменяемые, и некоторые компиляторы будут предупреждать вас об этом:
char *ptr = "Hello!" /* WRONG, missing const! */
Причина, как отмечали другие, в том, что строковые литералы могут храниться в неизменяемой части память программы.
Правильная «аннотация» для вас - убедиться, что у вас есть указатель на константу char:
const char *ptr = "Hello!"
И теперь вы непосредственно видите, что вы не можете изменять текст, хранящийся в указателе.
Если Вы используете строковый литерал «Hello!»
, сам литерал становится массивом из 7 символов и сохраняется где-то в памяти данных. Эта память может быть только для чтения.
Оператор
char *ptr = "Hello!";
определяет указатель на char
и инициализирует его, сохраняя в нем адрес начала литерала (этот массив из 7 символов, упомянутый ранее). Изменение содержимого памяти, на которую указывает ptr
, является незаконным.
Оператор
char ptr[] = "Hello!";
определяет массив char
( char ptr [7]
) и инициализирует его, копируя символы из литерала в массив. Массив можно изменять.
Строки в C - это массивы символов. Указатель - это переменная, которая содержит ячейку памяти другой переменной. Массив - это набор упорядоченных элементов данных. когда вы помещаете (* ptr) ++, вы получаете ошибку сегментации с помощью указателя.
Возможно, вы добавляете 1 ко всей строке (с указателем) вместо добавления 1 к первому символу переменной (с массивом).
Прочтите FAQ по языку C. Особенно массив и разделы указателей .