Может кто-нибудь объяснить, почему это работает с указателем:
char * str1;
str1 = "Hello1";
str1 = "new string";
// but not this
char str2 [] = "hello";
str2 = "four";
// or this
char str3 [];
str3 = "hello";
str3 = "hello";
Может кто-нибудь объяснить, почему это работает с указателем:
char * str1;
str1 = "Hello1";
str1 = "new string";
// but not this
char str2 [] = "hello";
str2 = "four";
// or this
char str3 [];
str3 = "hello";
str3 = "hello";
Почему это работает с указателями:
Когда вы говорите char * str1
в C, вы выделяете указатель в памяти. Когда вы пишете str1 = "Hello";
, вы создаете строковый литерал в памяти и указываете на него указатель. Когда вы создаете другой строковый литерал "new string"
и назначаете его str1
, все, что вы делаете, меняется там, где указывает указатель.
Почему это не работает с массивами:
Когда вы говорите char str2 [] = "Hello"
, вы создаете строковый литерал и помещаете его в массив во время его определения. Достаточно не указывать размер, так как массив вычисляет его и добавляет к нему '\0'
. Вы не можете переназначить что-либо в этот массив без изменения его размера. Вот почему str2 = "four"
не будет работать.
В случае str3
это тот же случай. Вы не определили размер массива в определении, поэтому он рассчитал его размер равным 0. Вы не можете назначить что-либо новое без изменения размера массива.
Массив и указатель - это разные вещи, поэтому. Вы можете назначить указатель, но вы не можете назначить массив. Особое исключение делается для инициализации массивов char со строковыми литералами.
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`
Строковые литералы (такие как "Привет" ) имеют тип char[N]
, где N
- количество символов (включая завершающий '\0'
). Массив может быть преобразован в указатель на его первый элемент, но массивы и указатели - это не одно и то же, что могут сказать некоторые плохие книги или учителя.
Проще говоря, потому что массив не является первоклассным объектом в C/С++. Единственный способ назначить массиву - использовать str (n) cpy или memcpy.
В то время как массив сбрасывается в указатель при передаче функции, невозможно назначить массив, за исключением момента компиляции в качестве инициализации.
Это просто потому, что, когда вы пишете этот код:
char str2 [] = "hello";
или даже:
int arr[] = {1,2,4,4,5};
он создает str2
или arr
как константный указатель. Поэтому вы не можете переназначить любые другие значения этим указателям, а в более позднем случае вы создаете нормальный указатель, и вы можете назначить ему что-либо.
Случай с указателями
Это работает, потому что, когда вы назначаете как str1="Hello"
, вы на самом деле создаете строковый литерал с именем hello, выделяя его где-то в памяти и назначая указателю первый символ литерала указателю, а поскольку указатель не является константой, вы может назначить его снова с разными адресами. Еще одним важным моментом является то, что строковый литерал создан в памяти только для чтения.
Случай с символьным массивом Вы можете назначить ему строковый литерал, в то время как инициализация будет поддерживаться языком. И не путайте назначение с инициализацией. В то время как назначение, так как его массив символов вы должны изменить символ значения по символу, вы пытаетесь адресовать первый адрес строкового литерала к первому символу массива (имя массива возвращает адрес первого элемента массив). И это явно неверно, поскольку первый элемент не является указателем, он не может хранить адрес.