В Си тип строкового литерала равен char[]
- это не const
в зависимости от типа, но это неопределенное поведение для изменения содержимого.Кроме того, 2 разных строковых литерала, которые имеют одинаковое содержимое (или достаточно одного и того же содержимого), могут или не могут использовать одни и те же элементы массива.
Из стандарта C99 6.4.5 / 5 «Строковые литералы - семантика»:
На этапе преобразования 7 байт или код нулевого значения добавляются к каждой многобайтовой последовательности символовэто результат строкового литерала или литералов.Последовательность многобайтовых символов затем используется для инициализации массива статической длительности хранения и длины, достаточной только для того, чтобы содержать последовательность.Для строковых литералов символов элементы массива имеют тип char
и инициализируются отдельными байтами многобайтовой последовательности символов;для широких строковых литералов элементы массива имеют тип wchar_t
и инициализируются последовательностью широких символов ...
Не определено, различаются ли эти массивы при условии, что их элементы имеют соответствующие значения.Если программа пытается изменить такой массив, поведение не определено.
В C ++ «Обычный строковый литерал имеет тип« массив n const char
»» (из 2.13.4 / 1).«Строковые литералы»).Но в стандарте C ++ есть особый случай, когда указатель на строковые литералы легко конвертируется в неконстантные указатели (4.2 / 2 «Преобразование массива в указатель»):
Строковый литерал(2.13.4), который не является широким строковым литералом, может быть преобразован в значение типа «указатель на символ»;широкий строковый литерал может быть преобразован в значение типа «указатель на wchar_t».
В качестве примечания: поскольку массивы в C / C ++ легко преобразуются в указатели, строковый литерал часто может бытьиспользуется в контексте указателя, так же, как любой массив в C / C ++.
Дополнительная редакторская обработка: то, что следует, на самом деле состоит в основном из моих предположений об обосновании выбора стандартов C и C ++ в отношении строкибуквальные типы.Поэтому возьмите его с крошкой соли (но, пожалуйста, прокомментируйте, если у вас есть исправления или дополнительные сведения):
Я думаю, что стандарт C решил сделать строковые литералы неконстантными типами, потому что было (и есть) такбольшой объем кода, который предполагает возможность использования неконстантных char
указателей, которые указывают на литералы.Когда был добавлен квалификатор const
(что, если я не ошибаюсь, было сделано во время стандартизации ANSI, но спустя много времени после того, как K & R C накопил тонну существующего кода), если они делали указатели на строковые литералы только способнымибыть назначенным на char const*
типов без приведения, почти каждая существующая программа потребовала бы изменения.Не очень хороший способ получить принятый стандарт ...
Я считаю, что изменение в C ++, что строковые литералы квалифицированы const
, было сделано главным образом для поддержки возможности литеральной строки более точно соответствовать перегрузке, которая принимаетАргумент "char const*
".Я думаю, что было также желание закрыть видимую дыру в системе типов, но эта дыра была в значительной степени открыта обратно специальным случаем в преобразованиях массива в указатель.
Приложение D стандарта указываетчто «неявное преобразование из const в неконстантную квалификацию для строковых литералов (4.2) устарело», но я думаю, что столько кода все равно сломается, что пройдет много времени, прежде чем разработчики компиляторов или комитет по стандартам захотят на самом делепотяните за вилку (если не будет изобретена какая-то другая хитрая техника - но тогда дыра вернется, не так ли?).