Почему я не могу записать строковый литерал, пока я * могу * записать строковый объект? - PullRequest
5 голосов
/ 04 января 2012

Если я определю что-то вроде ниже,

char  *s1 = "Hello";

почему я не могу сделать что-то вроде ниже,

*s1 = 'w'; // gives segmentation fault ...why???

Что если я сделаю что-то вроде ниже,

string s1 = "hello";

Могу ли я сделать что-то вроде ниже,

*s1 = 'w'; 

Ответы [ 4 ]

10 голосов
/ 04 января 2012

Потому что "Hello" создает const char [].Это распадается до const char*, а не char*.В C ++ строковые литералы доступны только для чтения.Вы создали указатель на такой литерал и пытаетесь записать в него.

Но когда вы делаете

string s1 = "hello";

Вы копируете const char * "hello" в s1,Разница в том, что в первом примере s1 указывает на только для чтения «привет», а во втором примере «только для чтения» «привет» копируется в неконстантный s1, позволяя вам получить доступ к элементам в скопированной строке, чтобы делать с ними то, что вы хотите.

Если вы хотите сделать то же самое с char *, вам нужно выделить место для данных char и скопировать в них привет

char hello[] = "hello"; // creates a char array big enough to hold "hello"
hello[0] = 'w';           //  writes to the 0th char in the array
2 голосов
/ 04 января 2012

строковые литералы обычно размещаются в сегменте данных только для чтения.

1 голос
/ 04 января 2012

Время путать вопросы:

char s0[] = "Hello";
s0[0] = 'w';

Это совершенно верно!Конечно, это не отвечает на первоначальный вопрос, так что здесь мы идем: строковые литералы создаются в постоянной памяти.То есть их тип равен char const[n], где n - это размер строки (включая завершающий нулевой символ, т. Е. n == 6 для строкового литерала "Hello". Но почему, о, почему этот тип может использоваться дляинициализировать char const*? Ответ - просто обратная совместимость или совместимость со [старым] кодом C: к тому времени, когда const перешел на язык, многие места уже инициализировали char* строковыми литералами. Любой приличный компилятор долженоднако предупредите об этом злоупотреблении.

1 голос
/ 04 января 2012

Поскольку Hello находится в постоянной памяти. Ваша подпись должна быть на самом деле

const char* s1 = "Hello";

Если вам нужен изменяемый буфер, объявите s1 как char[]. std::string перегружает operator [], так что вы можете индексировать в нем, т.е.

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