Почему строка может быть назначена указателю char *, но не массиву char []? - PullRequest
60 голосов
/ 24 июля 2011

Может кто-нибудь объяснить, почему это работает с указателем:

char * str1;

str1 = "Hello1";

str1 = "new string";

// but not this
char str2 [] = "hello";
str2 = "four";

// or this
char str3 [];
str3 = "hello";
str3 = "hello";

Ответы [ 5 ]

77 голосов
/ 24 июля 2011

Почему это работает с указателями:
Когда вы говорите char * str1 в C, вы выделяете указатель в памяти.Когда вы пишете str1 = "Hello";, вы создаете строковый литерал в памяти и указатель указывает на него.Когда вы создаете другой строковый литерал "new string" и присваиваете ему str1, все, что вы делаете, это изменяете, куда указывает указатель.

Почему он не работает с массивами:
Когда вы говорите char str2 [] = "Hello", вы создаете строковый литерал и помещаете его в массив во время его определения.Можно не указывать размер, так как массив вычисляет его и добавляет к нему '\0'.Вы не можете ничего переназначить этому массиву без изменения его размера.Вот почему str2 = "four" не будет работать.

В случае str3 это тот же случай.Вы не определили размер массива в определении, поэтому он вычислил его размер равным 0. Вы не можете назначить что-либо новое без изменения размера массива.

19 голосов
/ 24 июля 2011

Массив и указатель - разные вещи, поэтому.Вы можете назначить указатель, но вы не можете назначить массив.Специальное исключение сделано для инициализации массивов символов строковыми литералами.

char a[] = "Hello"; //initialize a char array with string literal. Special case, OK
char* p = "Hello"; //initializa a pointer with an array(which gets converted to pointer)
p = "My";   //assign pointer to point to another value. OK
a = "My";   //error, arrays cannot be assigned to. Use `strcpy`

Строковые литералы (например, «Hello») имеют тип char[N], где N - количество символов (включая завершающий символ *).1006 *).Массив можно преобразовать в указатель на его первый элемент, но массивы и указатели - это не одно и то же, что бы ни говорили плохие книги или учителя.

7 голосов
/ 24 июля 2011

Проще говоря, потому что массив не является первоклассным объектом в C / C ++.Единственный способ присвоения массиву - использовать str (n) cpy или memcpy.

Хотя массив сворачивается в указатель при передаче в функцию, невозможно присвоить массиву, кроме как ввремя компиляции как инициализация.

3 голосов
/ 27 февраля 2017

Случай с указателями Это работает, потому что, когда вы присваиваете как str1="Hello", вы фактически создаете строковый литерал с именем hello, выделяя его где-то в памяти, и присваиваете адрес первого символабуквально к указателю, и так как указатель не является постоянным, вы можете назначить его снова с другими адресами.И еще один важный момент, который следует отметить, заключается в том, что созданный строковый литерал находится в постоянной памяти.

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

3 голосов
/ 23 июля 2013

Это просто потому, что когда вы пишете этот код:

char str2 [] = "hello";

или даже:

int arr[] = {1,2,4,4,5};

создает str2 или arr как постоянный указатель. Вот почему вы не можете переназначать любые другие значения этим указателям, в то время как в последующем вы создаете обычный указатель и можете назначить ему что угодно.

...