Стандарт C ++ 11 (ISO / IEC 14882: 2011) гласит § C.1.1
:
char* p = "abc"; // valid in C, invalid in C++
Для C ++ все нормально, так как указатель на строковый литерал вреден, поскольку любая попытка его изменить приводит к сбою. Но почему это действительно в C?
C ++ 11 также говорит:
char* p = (char*)"abc"; // OK: cast added
Это означает, что если приведение добавлено к первому утверждению, оно становится действительным.
Почему приведение делает второй оператор действительным в C ++ и чем он отличается от первого? Разве это не вредно? Если это так, то почему стандарт сказал, что все в порядке?
char[]
во-первых. Второйconst_cast
замаскированный.OK
.const
, поэтому их не обязательно былоconst
.Ответы:
До C ++ 03 ваш первый пример был верным, но в нем использовалось неявное неявное преобразование - строковый литерал должен рассматриваться как тип
char const *
, поскольку вы не можете изменять его содержимое (не вызывая неопределенного поведения).Начиная с C ++ 11, неявное преобразование, которое было объявлено устаревшим, было официально удалено, поэтому код, который зависит от него (как ваш первый пример), больше не должен компилироваться.
Вы отметили один способ разрешить компиляции кода: хотя неявное преобразование было удалено, явное преобразование все еще работает, поэтому вы можете добавить приведение. Я бы не , однако, считаю это «фиксацию» кода.
Чтобы исправить код, нужно изменить тип указателя на правильный тип:
Что касается того, почему это было разрешено в C ++ (и до сих пор в C): просто потому, что существует много существующего кода, который зависит от этого неявного преобразования, и нарушение этого кода (по крайней мере, без какого-либо официального предупреждения), по-видимому, казалось стандартным комитетам вроде плохая идея
источник
char const *p = "abc";
является «действительным и безопасно в обоих C и C ++», а не «действует и безопасно в любом C или C ++».Это действительно в C по историческим причинам. Традиционно C указывал, что тип строкового литерала был
char *
скорее, чемconst char *
, хотя он уточнил это, сказав, что вы на самом деле не можете изменять его.Когда вы используете приведение, вы, по сути, говорите компилятору, что вы знаете лучше, чем правила сопоставления типов по умолчанию, и это делает назначение ОК.
источник
char[N]
и было изменено наconst char[N]
. К нему прикреплена информация о размере.char[N]
но не,char*
например,"abc"
естьchar[4]
Вы также можете использовать strdup :
источник