Строковая литерал
Синтаксис
"s-char-seq (необязательно)" | (1) | |
R"d-char-seq (необязательно)(r-char-seq (необязательно))d-char-seq (необязательно)" | (2) | (с C++11) |
L"s-char-seq (необязательно)" | (3) | |
LR"d-char-seq (необязательно)(r-char-seq (необязательно))d-char-seq (необязательно)" | (4) | (с C++11) |
u8"s-char-seq (необязательно)" | (5) | (с C++11) |
u8R"d-char-seq (необязательно)(r-char-seq (необязательно))d-char-seq (необязательно)" | (6) | (с C++11) |
u"s-char-seq (необязательно)" | (7) | (с C++11) |
uR"d-char-seq (необязательно)(r-char-seq (необязательно))d-char-seq (необязательно)" | (8) | (с C++11) |
U"s-char-seq (необязательно)" | (9) | (с C++11) |
UR"d-char-seq (необязательно)(r-char-seq (необязательно))d-char-seq (необязательно)" | (10) | (с C++11) |
Объяснение
| s-char-seq | - | Последовательность одного или нескольких s-char |
| s-char | - | Один из
|
| basic-s-char | - | Символ из набора символов перевода, за исключением двойной кавычки ", обратной косой черты \, или символа новой строки |
| d-char-seq | - | Последовательность одного или нескольких d-char , не более 16 символов длиной |
| d-char | - | Символ из основного набора символов, за исключением скобок, обратной косой черты и пробелов |
| r-char-seq | - | Последовательность одного или нескольких r-char , за исключением того, что она не должна содержать закрывающую последовательность )d-char-seq" |
| r-char | - | Символ из набора символов перевода |
| Синтаксис | Тип | Тип | Кодировка | ||||
|---|---|---|---|---|---|---|---|
| (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"; // can be true or false, unspecified const char* pc = "Hello"; char* p = const_cast<char*>(pc); p[0] = 'M'; // undefined behavior
Сырые строковые литералыСырые строковые литералы — это строковые литералы с префиксом, содержащим // OK: contains one backslash,
// equivalent to "\\"
R"(\)";
// OK: contains four \n pairs,
// equivalent to "\\n\\n\\n\\n"
R"(\n\n\n\n)";
// OK: contains one close-parenthesis, two double-quotes and one open-parenthesis,
// equivalent to ")\"\"("
R"-()""()-";
// OK: equivalent to "\n)\\\na\"\"\n"
R"a(
)\
a""
)a";
// OK: equivalent to "x = \"\"\\y\"\""
R"(x = ""\y"")";
// R"<<(-_-)>>"; // Error: begin and end delimiters do not match
// R"-()-"-()-"; // Error: )-" appears in the middle and terminates the literal | (с C++11) |
Инициализация
Объекты строковых литералов инициализируются последовательностью значений кодовых единиц, соответствующих последовательности s-char строковой литералы и r-char (с C++11), плюс завершающий нулевой символ (U+0000), в следующем порядке:
v — целое значение, представленное восьмеричным или шестнадцатеричным числом, составляющим последовательность цифр в escape-последовательности, и T — тип массива элементов строковой литералы (см. таблицу выше): - Если
vне превышает диапазон представимых значенийT, то escape-последовательность вносит одну кодовую единицу со значениемv. - В противном случае, если строковая литерал имеет синтаксис (1) или (3), и(с C++11)
vне превышает диапазон представимых значений соответствующего беззнакового типа для базового типаT, то escape-последовательность вносит одну кодовую единицу с уникальным значением типаT, которое совпадает с \(v \bmod 2^S\)v mod 2S, гдеS— ширинаT. - В противном случае программа неверна.
Конкатенация
Строковые литералы, расположенные рядом, конкатенируются на фазе 6 трансляции (после препроцессора). То есть, "Hello," " world!" даёт (единую) строку "Hello, world!". Если две строки имеют одинаковый префикс кодировки (или ни у одной нет префикса), то результирующая строка будет иметь тот же префикс кодировки (или не будет иметь префикса).
| Если у одной из строк есть префикс кодировки, а у другой нет, то у той, у которой нет префикса, он будет считаться таким же, как у другой. L"Δx = %" PRId16 // at phase 4, PRId16 expands to "d"
// at phase 6, L"Δx = %" and "d" form 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) |
| Префикс кодировки не разрешен в этих контекстах. Каждое имя универсального символа и каждая простая escape-последовательность в неоцениваемой строке заменяются членом набора символов перевода, который она обозначает. Неоцениваемая строка, содержащая числовую escape-последовательность или управляющую escape-последовательность, некорректна. | (с 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, but the array has size 8
Если за шестнадцатеричной escape-последовательностью в строковом литерале следует допустимая шестнадцатеричная цифра, то это будет считаться неверной escape-последовательностью. Для решения этой проблемы можно использовать конкатенацию строк:
//const char* p = "\xfff"; // error: hexadecimal escape sequence out of range
const char* p = "\xff""f"; // OK: the literal is const char[3] holding {'\xff','f','\0'}| Макрос проверки возможности | Значение | Стандарт | Функция |
|---|---|---|---|
__cpp_char8_t | 202207L |
(C++20) (DR) | Исправление совместимости и переносимости char8_t (разрешить инициализацию массивов (unsigned) char из строковых литералов UTF-8) |
__cpp_raw_strings | 200710L | (C++11) | Строковые литералы с сырыми строками |
__cpp_unicode_literals | 200710L | (C++11) | Строковые литералы с поддержкой Unicode |
Пример
#include <iostream>
char array1[] = "Foo" "bar";
// same as
char array2[] = { 'F', 'o', 'o', 'b', 'a', 'r', '\0' };
const char* s1 = R"foo(
Hello
World
)foo";
// same as
const char* s2 = "\nHello\n World\n";
// same as
const char* s3 = "\n"
"Hello\n"
" World\n";
const wchar_t* s4 = L"ABC" L"DEF"; // ok, same as
const wchar_t* s5 = L"ABCDEF";
const char32_t* s6 = U"GHI" "JKL"; // ok, same as
const char32_t* s7 = U"GHIJKL";
const char16_t* s9 = "MN" u"OP" "QR"; // ok, same as
const char16_t* sA = u"MNOPQR";
// const auto* sB = u"Mixed" U"Types";
// before C++23 may or may not be supported by
// the implementation; ill-formed since C++23
const wchar_t* sC = LR"--(STUV)--"; // ok, raw string literal
int main()
{
std::cout << array1 << ' ' << array2 << '\n'
<< s1 << s2 << s3 << std::endl;
std::wcout << s4 << ' ' << s5 << ' ' << sC
<< std::endl;
}Вывод:
Foobar Foobar Hello World Hello World Hello World ABCDEF ABCDEF STUV
Отчёты об ошибках
Следующие отчёты об ошибках, изменяющие поведение, были применены ретроактивно к ранее опубликованным стандартам C++.
| Отчёт об ошибке | Применён к | Опубликованное поведение | Корректное поведение |
|---|---|---|---|
|
CWG 411 (P2029R4) | C++98 | Escape-последовательности в строковых литералах не допускали отображения на несколько кодовых единиц | разрешено |
|
CWG 1656 (P2029R4) | C++98 | символы, обозначаемые числовыми escape- последовательностями в строковых литералах, были неясными | сделанными ясными |
| CWG 1759 | C++11 | литерал UTF-8 может содержать кодовые единицы, которые не могут быть представлены в char | char может представлять все кодовые единицы UTF-8 |
| CWG 1823 | C++98 | было ли определено, являются ли строковые литералы различными, было определено реализацией | различимость не определена, и один и тот же строковый литерал может давать различные объекты |
|
CWG 2333 (P2029R4) | C++11 | было неясно, разрешены ли числовые escape-последовательности в строковых литералах UTF-8/16/32 | сделано ясным |
| P1854R4 | C++98 | обычные и широкие строковые литералы с некодируемыми символами условно поддерживались | программы с такими литералами некорректны |
| P2029R4 | C++98 | 1. Было неясно, могут ли строковые литералы содержать некодируемые символы 2. Было неясно, могут ли строковые литералы содержать числовые escape-последовательности, так что кодовые единицы, которые они представляют, не могут быть представлены в типе элемента массива литералов | 1. условно поддерживались для обычных и широких строковых литералов[1] 2. Некорректны, если кодовые единицы не могут быть представлены в типе беззнакового целого числа, соответствующем базовому типу |
- P1854R4 был принят как отчёт об ошибке позже, отменяя это решение.
Ссылки
- Стандарт 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 для строковых литералов | |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/language/string_literal