String literal
Содержание |
Синтаксис
"
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 | - | Символ из basic source character set (until C++23) translation character set (since C++23) , за исключением двойной кавычки " , обратной косой черты \ или символа новой строки |
| d-char-seq | - | Последовательность из одного или более d-char ов, длиной не более 16 символов |
| d-char | - | Символ из basic source character set (until C++23) basic character set (since C++23) , за исключением круглых скобок, обратной косой черты и пробелов |
| r-char-seq | - |
Последовательность из одного или более
r-char
ов, за исключением того, что она не должна содержать закрывающую последовательность
)
d-char-seq
"
|
| r-char | - | Символ из basic source character set (until C++23) translation character set (since C++23) |
| Синтаксис | Вид | Тип | Кодировка | ||||
|---|---|---|---|---|---|---|---|
| (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 (since C++11) строковые литералы вместе называются узкими строковыми литералами.
Вычисление строкового литерала приводит к созданию объекта строкового литерала со статической продолжительностью хранения . Хранятся ли все строковые литералы в неперекрывающихся объектах и приводят ли последовательные вычисления строкового литерала к одному и тому же или разным объектам - не определено.
Эффект от попытки модификации строкового литерального объекта не определён.
bool b = "bar" == 3 + "foobar"; // может быть true или false, не определено const char* pc = "Hello"; char* p = const_cast<char*>(pc); p[0] = 'M'; // неопределенное поведение
Сырые строковые литералы
Сырые строковые литералы — это строковые литералы с префиксом, содержащим
// 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), в следующем порядке:
T
как тип элемента массива строкового литерала (см. таблицу
выше
):
-
Если
v
не превышает диапазон представимых значений типа
T, то escape-последовательность добавляет одну кодовую единицу со значением v . -
Иначе, если
строковый литерал имеет синтаксис
(1)
или
(3)
, и
(начиная с C++11)
v
не превышает диапазон представимых значений соответствующего беззнакового типа для базового типа
T, то escape-последовательность добавляет одну кодовую единицу с уникальным значением типаT, которое сравнимо с v mod 2 S
, где S — это ширинаT. - Иначе программа является некорректной.
Конкатенация
Смежные строковые литералы объединяются на фазе трансляции 6 (после препроцессинга):
- Если два строковых литерала одного типа , то объединённый строковый литерал также будет этого типа.
|
(until C++11) | ||||
|
(since C++11) |
"Hello, " "world!" // на фазе 6, 2 строковых литерала образуют "Hello, world!" L"Δx = %" PRId16 // на фазе 4, PRId16 раскрывается в "d" // на фазе 6, L"Δx = %" и "d" образуют L"Δx = %d"
- ↑ Ни одна известная реализация не поддерживает такую конкатенацию.
Невычисляемые строки
Следующие контексты ожидают строковый литерал, но не вычисляют его:
- language linkage спецификация
| (начиная с C++11) | |
|
(начиная с C++14) |
|
(начиная с C++20) |
| (начиная с C++26) |
|
Не указано, разрешены ли необычные строковые литералы в этих контекстах , за исключением того, что имя литерального оператора должно использовать обычный строковый литерал (since C++11) . |
(until C++26) |
|
Только обычные строковые литералы разрешены в этих контекстах. Каждое универсальное имя символа и каждая простая escape-последовательность в невычисляемой строке заменяется членом набора символов трансляции , который она обозначает. Невычисляемая строка, содержащая числовую escape-последовательность или условную escape-последовательность, является некорректной. |
(since C++26) |
Примечания
Строковые литералы могут использоваться для инициализации символьных массивов . Если массив инициализируется как char str [ ] = "foo" ; , str будет содержать копию строки "foo" .
|
Строковые литералы конвертируемы и присваиваемы к не-const char * или wchar_t * для совместимости с C, где строковые литералы имеют типы char [ N ] и wchar_t [ N ] . Такая неявная конвертация устарела. |
(until C++11) |
|
Строковые литералы не конвертируемы и не присваиваемы к не-const
|
(since C++11) |
Строковый литерал не обязательно является нуль-терминированной последовательностью символов: если строковый литерал содержит встроенные нулевые символы, он представляет массив, содержащий более одной строки.
const char* p = "abc\0def"; // std::strlen(p) == 3, но массив имеет размер 8
Если допустимая шестнадцатеричная цифра следует за шестнадцатеричной escape-последовательностью в строковом литерале, это приведет к ошибке компиляции как недопустимая escape-последовательность. В качестве обходного решения можно использовать конкатенацию строк:
//const char* p = "\xfff"; // ошибка: шестнадцатеричная escape-последовательность вне диапазона const char* p = "\xff""f"; // OK: литерал имеет тип const char[3] содержащий {'\xff','f','\0'}
| Макрос тестирования возможностей | Значение | Стандарт | Возможность |
|---|---|---|---|
__cpp_char8_t
|
202207L
|
(C++23)
(DR20) |
char8_t исправление совместимости и переносимости (разрешает инициализацию ( unsigned ) char массивов из строковых литералов UTF-8) |
__cpp_raw_strings
|
200710L
|
(C++11) | Сырые строковые литералы |
__cpp_unicode_literals
|
200710L
|
(C++11) | Юникодные строковые литералы |
Пример
#include <iostream> // array1 и array2 содержат одинаковые значения: char array1[] = "Foo" "bar"; char array2[] = {'F', 'o', 'o', 'b', 'a', 'r', '\0'}; const char* s1 = R"foo( Hello World )foo"; // то же самое, что const char* s2 = "\nHello\n World\n"; // то же самое, что const char* s3 = "\n" "Hello\n" " World\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"Mixed" U"Types"; // до 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 Hello World Hello World Hello World ABCDEF ABCDEF STUV
Отчеты о дефектах
Следующие отчеты об изменениях в поведении, являющиеся дефектными, были применены ретроактивно к ранее опубликованным стандартам C++.
| DR | Применяется к | Поведение в опубликованной версии | Корректное поведение |
|---|---|---|---|
|
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 строковых литералах |
прояснено |
| CWG 2870 | C++11 |
результат конкатенации двух
обычных строковых литералов был неясен |
прояснено |
| P1854R4 | C++98 |
обычные и широкие строковые литералы с некодируемыми
символами были условно-поддерживаемыми |
программы с такими литералами являются некорректными |
| P2029R4 | C++98 |
1. было неясно, могут ли строковые литералы
содержать некодируемые символы 2. было неясно, могут ли строковые литералы содержать числовые escape-последовательности, такие что кодовые единицы, которые они представляют, не представимы в типе элемента массива литералов |
1. сделано условно-поддерживаемым для
обычных и широких строковых литералов [1] 2. некорректно, если кодовые единицы не представимы ни в беззнаковом целочисленном типе, соответствующем базовому типу |
- ↑ P1854R4 был принят как Defect Report позднее, отменяя данное решение.
Ссылки
- Стандарт C++23 (ISO/IEC 14882:2024):
-
- 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 documentation
для
Строковые литералы
|
|