Строковый литерал
Содержание |
[править] Синтаксис
" последовательность-s-символов (необязательно)"
|
(1) | ||||||||
R" последовательность-d-символов (необязательно)( последовательность-r-символов (необязательно)) последовательность-d-символов (необязательно)"
|
(2) | (начиная с C++11) | |||||||
L" последовательность-s-символов (необязательно)"
|
(3) | ||||||||
LR" последовательность-d-символов (необязательно)( последовательность-r-символов (необязательно)) последовательность-d-символов (необязательно)"
|
(4) | (начиная с C++11) | |||||||
u8" последовательность-s-символов (необязательно)"
|
(5) | (начиная с C++11) | |||||||
u8R" последовательность-d-символов (необязательно)( последовательность-r-символов (необязательно)) последовательность-d-символов (необязательно)"
|
(6) | (начиная с C++11) | |||||||
u" последовательность-s-символов (необязательно)"
|
(7) | (начиная с C++11) | |||||||
uR" последовательность-d-символов (необязательно)( последовательность-r-символов (необязательно)) последовательность-d-символов (необязательно)"
|
(8) | (начиная с C++11) | |||||||
U" последовательность-s-символов (необязательно)"
|
(9) | (начиная с C++11) | |||||||
UR" последовательность-d-символов (необязательно)( последовательность-r-символов (необязательно)) последовательность-d-символов (необязательно)"
|
(10) | (начиная с C++11) | |||||||
[править] Объяснение
последовательность-s-символов | — | Последовательность из одного или нескольких s-символов |
s-символ | — | Один из
|
базовый-s-символ | — | Символ из набора символов трансляции, за исключением двойной кавычки ", обратной косой черты \ или символа новой строки |
последовательность-d-символов | — | Последовательность из одного или нескольких d-символов длиной не более 16 символов |
d-символ | — | Символ из базового набора символов, за исключением круглых скобок, обратной косой черты и пробельных символов |
последовательность-r-символов | — | Последовательность из одного или нескольких r-символов , за исключением того, что она не должна содержать закрывающую ) последовательность-d-символов"
|
r-символ | — | Символ из набора символов трансляции |
Синтаксис | Вид | Тип | Кодирование | ||||
---|---|---|---|---|---|---|---|
(1,2) | обычный строковый литерал | const char[N] | обычное литеральное кодирование | ||||
(3,4) | широкий строковый литерал | const wchar_t[N] | широкое литеральное кодирование | ||||
(5,6) | строковый литерал UTF-8 |
|
UTF-8 | ||||
(7,8) | строковый литерал UTF-16 | const char16_t[N] | UTF-16 | ||||
(9,10) | строковый литерал UTF-32 | const char32_t[N] | UTF-32 |
В типах, перечисленных в таблице выше, N это количество кодированных кодовых единиц, которое определяется ниже.
Обычные и UTF-8 (начиная с C++11) строковые литералы вместе называются узкими строковыми литералами.
Результатом вычисления строкового литерала является объект строкового литерала со статической длительностью хранения. Сохраняются ли все строковые литералы в непересекающихся объектах и дают ли последовательные вычисления строкового литерала тот же или другой объект, не указано.
Эффект от попытки изменить объект строкового литерала не определён.
bool b = "bar" == 3 + "foobar"; // может быть true или false, не указано const char* pc = "Привет"; char* p = const_cast<char*>(pc); p[0] = 'M'; // неопределённое поведение
Сырые строковые литералыСырые строковые литералы это строковые литералы с префиксом, содержащим // OK: содержит одну обратную косую черту, // эквивалентно "\\" R"(\)"; // OK: содержит четыре пары \n, // эквивалентно "\\n\\n\\n\\n" R"(\n\n\n\n)"; // OK: содержит одну закрывающую скобку, две двойные кавычки // и одну открывающую скобку, // эквивалентно ")\"\"(" R"-()""()-"; // OK: эквивалентно "\n)\\\na\"\"\n" R"a( )\ a"" )a"; // OK: эквивалентно "x = \"\"\\y\"\"" R"(x = ""\y"")"; // R"<<(-_-)>>"; // Ошибка: начальный и конечный разделители не совпадают // R"-()-"-()-"; // Ошибка: )-" появляется посередине и завершает литерал |
(начиная с C++11) |
[править] Инициализация
Объекты строковых литералов инициализируются последовательностью значений кодовых единиц, соответствующей последовательности строковых литералов s-символов и r-символов (начиная с C++11) плюс завершающий нулевой символ (U+0000) в следующем порядке:
T
как тип элемента массива строкового литерала (смотрите таблицу выше):
- Если v не выходит за пределы диапазона представимых значений
T
, то управляющая последовательность вносит одну кодовую единицу со значением v. - Иначе, если строковый литерал имеет синтаксис (1) или (3), и (начиная с C++11) v не выходит за пределы диапазона представимых значений соответствующего беззнакового типа для базового типа
T
, то управляющая последовательность вносит одну кодовую единицу с уникальным значением типаT
, которое соответствует v mod 2S
, где S это ширинаT
. - Иначе программа будет некорректной.
[править] Конкатенация
Строковые литералы, расположенные рядом, объединяются на фазе трансляции 6 (после препроцессора). То есть "Привет," " мир!" возвращает (одну) строку "Привет, мир!". Если две строки имеют одинаковый префикс кодировки (или ни одна из них не имеет его), результирующая строка будет иметь тотже префикс кодировки (или не будет иметь префикса).
Если одна из строк имеет префикс кодировки, а другая нет, будет считаться, что та, у которой его нет, имеет тот же префикс кодировки, что и другая. L"Δx = %" PRId16 // в фазе 4, PRId16 расширяется до "d" // в фазе 6, L"Δx = %" и "d" образуют L"Δx = %d" Если строковый литерал UTF-8 и широкий строковый литерал расположены рядом, программа некорректна. |
(начиная с C++11) |
Любая другая комбинация префиксов кодировки условно поддерживается семантикой, определяемой реализацией. (Ни одна известная реализация не поддерживает такую конкатенацию.) |
(начиная с C++11) (до C++23) |
Любая другая комбинация префиксов кодировки является неправильной. |
(начиная с C++23) |
[править] Неоценённые ст��оки
Следующие контексты ожидают строковый литерал, но не оценивают его:
- спецификация языкового связывания
-
static_assert
(начиная с C++11) - имя литерального оператора (начиная с C++11)
-
[[deprecated]]
(начиная с C++14) -
[[nodiscard]]
(начиная с C++20)
Не указано, разрешён ли префикс кодировки в этих контекстах (за исключением того, что имя литерального оператора не должно иметь префикса кодировки) (начиная с C++11). |
(до C++26) |
В этих контекстах не допускается использование префикса кодировки. Каждое универсальное имя символа и каждая простая управляющая последовательность в неоценённой строке заменяется элементом набора символов трансляции, который оно обозначает. Неоценённая строка, содержащая числовую управляющую последовательность или условную управляющую последовательность, неправильна. |
(начиная с C++26) |
[править] Примечание
Строковые литералы можно использовать для инициализации массивов символов. Если массив инициализируется как char str[] = "foo";, str будет содержать копию строки "foo".
Строковые литералы можно конвертировать и присваивать неконстантным char* или wchar_t* для совместимости с C, где строковые литералы имеют типы char[N] и wchar_t[N]. Такое неявное преобразование устарело. |
(до C++11) |
Строковые литералы нельзя конвертировать или присваивать неконстантным |
(начиная с C++11) |
Строковый литерал не обязательно является последовательностью символов, завершающейся нулём: если строковый литерал содержит встроенные нулевые символы, он представляет собой массив, содержащий более одной строки.
const char* p = "abc\0def"; // std::strlen(p) == 3, но массив имеет размер 8
Если за шестнадцатеричной управляющей последовательностью в строковом литерале следует допустимая шестнадцатеричная цифра, она не сможет скомпилироваться как допустимая управляющая последовательность. В качестве обходного пути можно использовать конкатенацию строк:
//const char* p = "\xfff"; // ошибка: шестнадцатеричная управляющая последовательность // вне диапазона const char* p = "\xff""f"; // OK: литерал это const char[3], содержащий {'\xff','f','\0'}
Макрос тест функциональности | Значение | Стандарт | Комментарий |
---|---|---|---|
__cpp_char8_t |
202207L | (C++20) | Исправление совместимости и переносимости char8_t (позволяет инициализировать массивы (unsigned) char из строковых литералов UTF-8) |
__cpp_raw_strings |
200710L | (C++11) | Сырые строковые литералы |
__cpp_unicode_literals |
200710L | (C++11) | Строковые литералы Юникода |
[править] Пример
#include <iostream> char array1[] = "Foo" "bar"; // то же, что и char array2[] = { 'F', 'o', 'o', 'b', 'a', 'r', '\0' }; const char* s1 = R"foo( Привет Мир )foo"; // то же, что и const char* s2 = "\nПривет\n Мир\n"; // то же, что и const char* s3 = "\n" "Привет\n" " Мир\n"; const wchar_t* s4 = L"ABC" L"DEF"; // ok, то же, что и const wchar_t* s5 = L"ABCDEF"; const char32_t* s6 = U"GHI" "JKL"; // ok, то же, что и const char32_t* s7 = U"GHIJKL"; const char16_t* s9 = "MN" u"OP" "QR"; // ok, то же, что и const char16_t* sA = u"MNOPQR"; // const auto* sB = u"Смешанные" U"Типы"; // пере�� C++23 может поддерживаться или не поддерживаться // реализацией; ошибка начиная с C++23 const wchar_t* sC = LR"--(STUV)--"; // ok, сырой строковый литерал int main() { std::cout << array1 << ' ' << array2 << '\n' << s1 << s2 << s3 << std::endl; std::wcout << s4 << ' ' << s5 << ' ' << sC << std::endl; }
Вывод:
Foobar Foobar Привет Мир Привет Мир Привет Мир ABCDEF ABCDEF STUV
[править] Отчёты о дефектах
Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:
Номер | Применён | Поведение в стандарте | Корректное поведение |
---|---|---|---|
CWG 411 | C++98 | управляющим последовательностям в строковых литералах не разрешалось сопоставлять несколько кодовых единиц |
позволено |
CWG 1656 | C++98 | символы, обозначаемые числовыми управляющими последовательностями в строковых литералах, были непонятны |
сделаны понятными |
CWG 1759 | C++11 | строковый литерал UTF-8 может иметь кодовые единицы, которые невозможно представить в char |
char может представлять все кодовые единицы UTF-8 |
CWG 1823 | C++98 | различны ли строковые литералы, определялось реализацией | различимость не указана, и один и тот же строковый литерал может давать разные объекты |
CWG 2333 | C++11 | было непонятно, разрешены ли числовые управляющие последовательности в строковых литералах UTF-8/16/32 |
сделано понятным |
WG не указан | C++98 | обычные и широкие строковые литералы с некодируемыми символами поддерживались условно |
программы с такими литералами некорректны |
WG не указан | C++98 | 1. было неясно, могут ли строковые литералы содержать некодируемые символы 2. было неясно, могут ли строковые литералы содержать числовые управляющие последовательности, так что кодовые единицы, которые они представляют, не могли быть представлены в типе элемента массива литералов |
1. сделана условная поддержка для обычных и широких строковых литералов[1] 2. неправильно сформировано, если кодовые единицы не могут быть представлены в целочисленном типе без знака, соответствующему базовому типу |
- ↑ P1854R4 позже была принята как DR, переопределив это разрешение.
[править] Ссылки
- C++23 стандарт (ISO/IEC 14882:2023):
- 5.13.5 Строковые литералы [lex.string]
- C++20 стандарт (ISO/IEC 14882:2020):
- 5.13.5 Строковые литералы [lex.string]
- C++17 стандарт (ISO/IEC 14882:2017):
- 5.13.5 Строковые литералы [lex.string]
- C++14 стандарт (ISO/IEC 14882:2014):
- 2.14.5 Строковые литералы [lex.string]
- C++11 стандарт (ISO/IEC 14882:2011):
- 2.14.5 Строковые литералы [lex.string]
- C++03 стандарт (ISO/IEC 14882:2003):
- 2.13.4 Строковые литералы [lex.string]
- C++98 стандарт (ISO/IEC 14882:1998):
- 2.13.4 Строковые литералы [lex.string]
[править] Смотрите также
определяемые пользователем литералы(C++11) | литералы с пользовательским суффиксом |
Документация C по Строковые литералы
|