Каков тип данных строкового литерала в С++?
Аналогичные вопросы заданы о типе данных строковых литералов в С++.
Многие люди процитировали стандарт:
Узкий строковый литерал имеет тип "массив из n const char", где n - размер строки, как определено ниже, и имеет статическую продолжительность хранения (3.7)
В основной функции я написал следующий оператор:
char cstring[]= "hellohellohellohellohellohello";
Но я не могу найти ни строковый литерал, который хранится как статические данные в сборке. Фактически, сборка показывает, что строка разлагается и "сохраняется" непосредственно в инструкциях.
movl $1819043176, -48(%rbp)
movl $1818585199, -44(%rbp)
movl $1701343084, -40(%rbp)
movl $1752132716, -36(%rbp)
movl $1869376613, -32(%rbp)
movl $1819043176, -28(%rbp)
movl $1818585199, -24(%rbp)
movw $28524, -20(%rbp)
movb $0, -18(%rbp)
В то время как аналогичный оператор в глобальной области имеет в результате строку, хранящуюся как статические данные.
char cstring1[] = "hellohellohellohellohellohello";
Сборка
cstring1:
.string "hellohellohellohellohellohello"
Приведенный выше пример доступен в Интернете здесь.
Таким образом, это не соответствует приведенному стандарту. Может быть, есть некоторые исключения из того, что здесь цитируется?
Ответы
Ответ 1
Выражения имеют тип. Строковые литералы имеют тип, если они используются как выражение. У вас нет.
Рассмотрим следующий код:
#include <stdio.h>
#define STR "HelloHelloHello"
char global[] = STR;
int main(void)
{
char local[] = STR;
puts(STR);
}
В этой программе, созданной с использованием жетонов, есть три строковых литерала, но они не обрабатываются одинаково.
Первый, инициализатор для global
, является частью статической инициализации объекта со статическим временем жизни. В разделе 3.6.2 статическая инициализация не должна выполняться во время выполнения; компилятор может организовать предварительный форматирование результата в двоичном изображении, чтобы процесс начал выполнение с уже существующими данными, и он сделал это здесь. Также было бы законно инициализировать этот объект так же, как local[]
, если он был выполнен до начала динамической инициализации глобальных символов.
Второй, инициализатор для local
, является строковым литералом, но на самом деле это не выражение. Он обрабатывается по специальным правилам 8.5.2, который гласит, что символы внутри строкового литерала независимо используются для инициализации элементов массива; строковый литерал не используется как единица. Этот объект имеет динамическую инициализацию, что приводит к загрузке значения во время выполнения.
Третий, аргумент для вызова puts()
, фактически использует строковый литерал как выражение, и он будет иметь тип const char[N]
, который распадается на const char*
для вызова. Если вы действительно хотите изучить объектный код, используемый для обработки типа исполняемого файла строкового литерала, вы должны использовать литерал в выражении, как это делает этот вызов функции.
Ответ 2
Он соответствует стандарту в соответствии с правилом "как есть".
Поскольку единственное, что используется для строкового литерала, это инициализировать cstring
, для него нет необходимости в каком-либо объектном представлении. Компилятор исключил его в пользу инициализации cstring
альтернативным способом, который имеет эквивалентные результаты, но что компилятор решает лучше в некотором отношении (скорость или размер кода).
Ответ 3
Я думаю, что определение, которое вы цитируете, должно интерпретироваться как ссылка на строковые литералы, чье местоположение хранения явно не объявлено, например выражение формата в printf()
. Для того, чтобы такой код работал, эти строковые литералы должны быть где-то сохранены; определение указывает, где они хранятся, если это невозможно сделать из контекста.
На стороне примечания: строковый литерал в вашем main()
не отображается как статические данные, поскольку переменные, объявленные в функциях, по умолчанию являются "автоматическими". Если бы вы вместо этого записали static char cstring[]=...
, вы бы увидели его там же, где cstring1[]
.
И еще одно: место хранения НЕ является частью типа данных!