Подтвердить что ты не робот

Почему преобразование из строковой константы в 'char *' допустимо в C, но недействительно в С++

Стандарт С++ 11 (ISO/IEC 14882: 2011) говорит в § C.1.1:

char* p = "abc"; // valid in C, invalid in C++

Для С++ это ОК как указатель на String Literal вреден, поскольку любая попытка его изменения приводит к сбою. Но почему это действительно в C?

В С++ 11 также говорится:

char* p = (char*)"abc"; // OK: cast added

Это означает, что если добавление в первый оператор будет добавлено, оно станет действительным.

Почему кастинг делает второй оператор действительным в С++ и чем он отличается от первого? Разве это еще не вредно? Если это так, почему стандарт сказал, что это нормально?

4b9b3361

Ответ 1

Вверх по С++ 03, ваш первый пример был действительным, но использовал устаревшее неявное преобразование - строковый литерал должен рассматриваться как имеющий тип char const *, так как вы не можете изменять его содержимое (не вызывая undefined).

Начиная с С++ 11, неявное преобразование, которое было устаревшим, было официально удалено, поэтому код, который зависит от него (например, ваш первый пример), больше не должен компилироваться.

Вы отметили один способ разрешить компиляцию кода: хотя неявное преобразование было удалено, явное преобразование все еще работает, поэтому вы можете добавить листинг. Однако я бы не подумал об этом "исправлении" кода.

Истинное исправление кода требует изменения типа указателя на правильный тип:

char const *p = "abc"; // valid and safe in either C or C++.

Что касается того, почему это было разрешено на С++ (и все еще находится в C): просто потому, что существует много существующего кода, который зависит от этого неявного преобразования, и нарушение этого кода (по крайней мере, без какого-либо официального предупреждения), по-видимому, казалось стандартные комитеты, как плохая идея.

Ответ 2

Он действителен в C по историческим причинам. C традиционно указывает, что тип строкового литерала был char *, а не const char *, хотя он квалифицировал его, говоря, что вам фактически не разрешено его изменять.

Когда вы используете бросок, вы, по сути, говорите компилятору, что знаете лучше, чем правила сопоставления по умолчанию по умолчанию, и он делает присвоение ОК.