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