Почему вот это приводит к ошибке времени исполнения:
int main()
{
char *p = "string";
p[1] = 'p';
return 0;
}
И почему код вообще компилируется, если в выражении char *p = "string"; тип слева равен char *, а тип справа равен const char*, или я что-то путаю?
Код приводит к "ошибке времени исполнения" (а точнее - к неопределенному поведению), потому что в языке C++ строковые литералы являются немодифицируемыми.
При этом в инициализации
char *p = "string";
тип слева - char *, а тип справа const char[7]. Такая инициализация является ошибочной в языке C++11 и позже.
В более ранних версиях языка (C++98 и С++03) такая инициализация являлась корректной, благодаря специальному исключению, сделанному именно для таких случаях в спецификации array-to-pointer conversion.
Если вы используете современный компилятор С++, то скорее всего у вас этот код НЕ компилируется, а вы сами этого просто не заметили, т.е. проигнорировали диагностическое сообщение компилятора.
У указателя нет модификатора const, поэтому, формально, изменение в области памяти по этому указателю не запрещено. Например в следующий момент вы можете присвоить указателю адрес на область памяти с неконстантным содержимым. Поэтому данный код не вызывает ошибки времени компиляции. Однако вызывает ошибку времени выполнения, потому что в данным момент указатель ссылается на неизменяемые данные. С++ язык со слабой типизацией, поэтому такие "фокусы" возможны.
Продвижение своими сайтами как стратегия роста и независимости