2013-08-24 2 views
5

Из любопытства, мне интересно, каков реальный базовый тип строкового литерала C++.Тип литерала строки C++

В зависимости от того, что я наблюдаю, у меня разные результаты.

Испытание TypeId как следующее:

std::cout << typeid("test").name() << std::endl; 

показывает мне char const[5].

Попытка присвоить строку литерала несовместимого типа как так (чтобы увидеть данную ошибку):

wchar_t* s = "hello"; 

Я получаю a value of type "const char *" cannot be used to initialize an entity of type "wchar_t *" от IntelliSense VS12 в.

Но я не вижу, как это может быть const char * как следующая строка принята VS12:

char* s = "Hello"; 

Я прочитал, что это позволило в 11 стандартов обработки перед C++ как это было ретро-совместимость с C, хотя модификация s приведет к Undefined Behavior. Я предполагаю, что это просто VS12, который еще не реализовал весь стандарт C++ 11 и что эта строка обычно приводит к ошибке.

Чтение стандарт C99 (from here, 6.4.5.5) предполагает, что он должен быть массивом:

многобайтовый символ последовательность затем используется для инициализации массив статической продолжительности хранения и длины всего , достаточный для сохранения последовательности.

Итак, Что такое тип под строковым литералом C++?

Большое спасибо за ваше драгоценное время.

+5

VS12 говорит какой-то странный диалект, который похож, но не идентичны, C++. –

ответ

8

Тип строкового литерала - это действительно const char[SIZE], где SIZE - длина строки плюс нуль-завершающий символ.

Тот факт, что вы иногда видите const char*, связан с обычным распадом матрицы-указателя.

Но я не вижу, как это может быть const char * как следующая строка принята VS12: char* s = "Hello";

Это было правильное поведение в C++ 03 (как исключение из обычного const-correctness), но с тех пор он устарел. Компилятор, совместимый с C++ 11, не должен принимать этот код.

+2

«Обычный разброс по матрице-указателю» не встречается во всех контекстах. В C это происходит, если выражение массива не является операндом унарного '' '' '' '' '' '' '' '' 'sizeof'' или является строковым литералом в инициализаторе, используемом для инициализации объекта массива (sub). C++ имеет больше исключений. –

+0

Правильный термин - это преобразование _Array-to-pointer_, которое является _Standard Conversion_, зарегистрированным в разделе 4 последнего стандарта C++. Грубо говоря, стандартные преобразования могут применяться неявно к выражениям компилятора в определенных контекстах. –

5

Тип строкового литерала - это номер char const[N], где N - количество символов, включая символ нулевого завершения. Хотя этот тип делает не конвертировать в char*, стандарт C++ включает в себя предложение, позволяющее присваивать строковый литерал до char*.Этот раздел был добавлен для поддержки совместимости, особенно для кода C, который тогда не имел const.

Соответствующий пункт для данного типа в стандарте 2.14.5 [lex.string] пункт 8:

Обычные строковые литералы и UTF-8 строковые литералы также называют узкими строковых литералов. Узкий строковый литерал имеет тип «массив из n const char», где n - размер строки, как определено ниже, и имеет статическую продолжительность хранения (3.7).

+1

Обратите внимание, что это исключительное предложение теперь устарело, и попытка присвоить строковый литерал для символа 'char *' должна давать ошибку времени компиляции. – syam

+0

@syam - «устаревший» означает, что он по-прежнему легален, но может уйти в будущем. Преобразование строкового литерала в 'char *' было устарело в C++ 03; он стал недействительным в C++ 11. Однако для определения языка не требуется «ошибка времени компиляции». Для нарушения диагностируемых ограничений единственным требованием является то, что компилятор выдает диагностику; сделав это, можно продолжить компиляцию кода. Это крючок для расширений, связанных с реализацией. Существует только одна ситуация, требующая от компилятора отказаться от компиляции кода: директива '# error'. –

-1

Во-первых, тип строки C++ буквального является массивом пconst char. Во-вторых, если вы хотите инициализировать wchar_t с строкового литерала вы должны код:

wchar_t* s = L"hello" 
+0

Это не предназначалось для действительного кода, а только для проверки данной ошибки. Стандарт действительно заставляет его звучать так, будто он должен быть массивом. –

+7

Нет, строковый литерал не является 'const char *', а 'const char [SIZE]', как описано в других ответах. -1 – syam

+1

Затем объясните, почему 'sizeof 'hello, world" 'дает 13. –

Смежные вопросы