Какой тип строкового литерала в C? Это char *, const char * или const char * const?
А как насчет C ++?
Какой тип строкового литерала в C? Это char *, const char * или const char * const?
А как насчет C ++?
В C типом строкового литерала является char[] - это не const в зависимости от типа, но это неопределенное поведение для изменения содержимого. Кроме того, два разных строковых литерала с одинаковым содержимым (или достаточным количеством одного и того же содержимого) могут или не могут использовать одни и те же элементы массива.
Из стандарта C99 6.4.5 / 5 «Строковые литералы - семантика»:
На этапе трансляции 7 байт или код нулевого значения добавляется к каждой многобайтовой символьной последовательности, которая получается из строкового литерала или литералов. Затем многобайтовая последовательность символов используется для инициализации массива статической продолжительности хранения и длины, достаточной для хранения последовательности. Для литералов символьной строки элементы массива имеют тип
charи инициализируются отдельными байтами многобайтовой последовательности символов; для широких строковых литералов элементы массива имеют типwchar_tи инициализируются последовательностью широких символов ...Не указано, являются ли эти массивы отдельными при условии, что их элементы имеют соответствующие значения. Если программа пытается изменить такой массив, поведение не определено.
В C ++: «Обычный строковый литерал имеет тип 'array of n const char'» (из 2.13.4 / 1 «Строковые литералы»). Но в стандарте C ++ есть особый случай, когда указатель на строковые литералы легко преобразуется в указатели, не квалифицированные константой (4.2 / 2 «Преобразование массива в указатель»):
Строковый литерал (2.13.4), который не является широким строковым литералом, может быть преобразован в rvalue типа «указатель на char»; широкий строковый литерал может быть преобразован в rvalue типа «указатель на 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) устарело», но я думаю, что так много кода все равно сломается, что пройдет много времени, прежде чем разработчики компилятора или комитет по стандартам готов фактически закрыть пробку (если не будет изобретен какой-нибудь другой умный метод - но тогда дыра вернется, не так ли?).
Строковый литерал C имеет тип char [n], где n равно количеству символов + 1 для учета неявного нуля в конце строки.
Массив будет размещен статически; это не const, но его изменение - неопределенное поведение.
Если бы он имел тип указателя char * или неполный тип char [], sizeof не мог бы работать должным образом.
Создание строковых литералов const - это идиома C ++, а не часть какого-либо стандарта C.
По разным историческим причинам строковые литералы всегда имели тип char[] в C.
Ранее (в C90) было заявлено, что изменение строкового литерала вызывает неопределенное поведение.
Однако они не запрещали такие модификации и не создавали строковые литералы const char[], которые имели бы больше смысла. Это было сделано из соображений обратной совместимости со старым кодом. Некоторые старые ОС (в первую очередь DOS) не возражали против изменения строковых литералов, поэтому такого кода было предостаточно.
В языке C этот недостаток все еще присутствует, даже в самом последнем стандарте C.
C ++ унаследовал тот же самый дефект от C, но в более поздних стандартах C ++ они, наконец, сделали строковые литералы const (помечены как устаревшие в C ++ 03, окончательно исправлены в C ++ 11).
Раньше они были типа char[]. Теперь они типа const char[].
char x[]="abc"; - это особый случай, который объявляет переменную типа char[4] и инициализирует ее, как указано. Это сокращение от char x[4] = {0x61,0x62,0x63,0};, поэтому строковый литерал не обрабатывается так, как другие. В частности, он не будет помещен компилятором в какое-либо безымянное место, как большинство строковых литералов.
- person greggo; 01.06.2015