Пространства имён
Варианты
Действия

Строковый литерал

Материал из cppreference.com
< cpp‎ | language
 
 
Язык С++
Общие темы
Управление потоком
Операторы условного выполнения
if
Операторы итерации (циклы)
Операторы перехода
Функции
Объявление функции
Выражение лямбда-функции
Спецификатор inline
Спецификации динамических исключений (до C++17*)
Спецификатор noexcept (C++11)
Исключения
Пространства имён
Типы
Спецификаторы
decltype (C++11)
auto (C++11)
alignas (C++11)
Спецификаторы длительности хранения
Инициализация
Выражения
Альтернативные представления
Литералы
Логические - Целочисленные - С плавающей запятой
Символьные - Строковые - nullptr (C++11)
Определяемые пользователем (C++11)
Утилиты
Атрибуты (C++11)
Types
Объявление typedef
Объявление псевдонима типа (C++11)
Casts
Неявные преобразования - Явные преобразования
static_cast - dynamic_cast
const_cast - reinterpret_cast
Выделение памяти
Классы
Свойства функции класса
explicit (C++11)
static
Специальные функции-элементы
Шаблоны
Разное
 
Выражения
Общие
Категории значений (lvalue, rvalue, xvalue)
Порядок оценки (точки последовательности)
Константные выражения
Потенциально оцениваемые выражения
Первичные выражения
Лямбда-выражения(C++11)
Литералы
Целочисленные литералы
Литералы с плавающей запятой
Логические литералы
Символьные литералы, включая управляющие последовательности
Строковые литералы
Литерал нулевого указателя(C++11)
Пользовательский литерал(C++11)
Операторы
a=b, a+=b, a-=b, a*=b, a/=b, a%=b, a&=b, a|=b, a^=b, a<<=b, a>>=b
++a, --a, a++, a--
+a, -a, a+b, a-b, a*b, a/b, a%b, ~a, a&b, a|b, a^b, a<<b, a>>b
a||b, a&&b, !a
a==b, a!=b, a<b, a>b, a<=b, a>=b, a<=>b (начиная с C++20)
a[b], *a, &a, a->b, a.b, a->*b, a.*b
a(...), a,b, a?b:c
выражение new
выражение delete
выражение throw
alignof
sizeof
sizeof...(C++11)
typeid
noexcept(C++11)
Выражения свёртки(C++17)
Альтернативные представления операторов
Приоритет и ассоциативность
Перегрузка операторов
Сравнение по умолчанию(C++20)
Преобразования
Неявные преобразования
Обычные арифметические преобразования
const_cast
static_cast
reinterpret_cast
dynamic_cast
Явные преобразования: (T)a, T(a), auto(a), auto{a} (начиная с C++23)
Пользовательское преобразование
 

Содержание

[править] Синтаксис

"последовательность-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

const char[N]

(до C++20)

const char8_t[N]

(начиная с C++20)
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'; // неопределённое поведение

Сырые строковые литералы

Сырые строковые литералы это строковые литералы с префиксом, содержащим R (синтаксисы (2,4,6,8,10)). Они не экранируют ни одного символа, что означает что-либо между разделителями последовательность-d-символов ( и )последовательность-d-символов становится частью строки. Завершающая последовательность-d-символов представляет собой ту же последовательность символов, что и начальная последовательность-d-символов.

// 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) в следующем порядке:

1) Для каждой непрерывной последовательности базовых-s-символов , r-символов , (начиная с C++11) простых управляющих последовательностей и универсальных имён символов, последовательность символов, которую она обозначает, кодируется в последовательность кодовых единиц, используя кодировку символов, связанную со строковым литералом. Если символу не хватает представления в соответствующей кодировке символов, программа некорректна.
Если соответствующая кодировка символов имеет состояние, первая такая последовательность кодируется, начиная с начального состояния кодирования, а каждая последующая последовательность кодируется, начиная с конечного состояния кодирования предыдущей последовательности.
2) Для каждой числовой управляющей последовательности задано v как целое значение, представленное восьмеричным или шестнадцатеричным числом, содержащим последовательность цифр в управляющей последовательности, и T как тип элемента массива строкового литерала (смотрите таблицу выше):
  • Если v не выходит за пределы диапазона представимых значений T, то управляющая последовательность вносит одну кодовую единицу со значением v.
  • Иначе, если строковый литерал имеет синтаксис (1) или (3), и (начиная с C++11) v не выходит за пределы диапазона представимых значений соответствующего беззнакового типа для базового типа T, то управляющая последовательность вносит одну кодовую единицу с уникальным значением типа T, которое соответствует v mod 2S
    , где S это ширина T.
  • Иначе программа будет некорректной.
Если связанная кодировка символов имеет состояние, все такие последовательности не влияют на состояние кодирования.
3) Каждая условная управляющая последовательность вносит определённую реализацией последовательность кодовых единиц.
Если связанная кодировка символов имеет состояние, то влияние, которое эти последовательности оказывают на состояние кодирования, определяется реализацией.

[править] Конкатенация

Строковые литералы, расположенные рядом, объединяются на фазе трансляции 6 (после препроцессора). То есть "Привет,"  " мир!" возвращает (одну) строку "Привет, мир!". Если две строки имеют одинаковый префикс кодировки (или ни одна из них не имеет его), результирующая строка будет иметь тотже префикс кодировки (или не будет иметь префикса).

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

L"Δx = %" PRId16 // в фазе 4, PRId16 расширяется до "d"
                 // в фазе 6, L"Δx = %" и "d" образуют L"Δx = %d"

Если строковый литерал UTF-8 и широкий строковый литерал расположены рядом, программа некорректна.

(начиная с C++11)


Любая другая комбинация префиксов кодировки условно поддерживается семантикой, определяемой реализацией. (Ни одна известная реализация не поддерживает такую конкатенацию.)

(начиная с C++11)
(до C++23)

Любая другая комбинация префиксов кодировки является неправильной.

(начиная с C++23)

[править] Неоценённые ст��оки

Следующие контексты ожидают строковый литерал, но не оценивают его:

Не указано, разрешён ли префикс кодировки в этих контекстах (за исключением того, что имя литерального оператора не должно иметь префикса кодировки) (начиная с C++11).

(до C++26)

В этих контекстах не допускается использование префикса кодировки.

Каждое универсальное имя символа и каждая простая управляющая последовательность в неоценённой строке заменяется элементом набора символов трансляции, который оно обозначает. Неоценённая строка, содержащая числовую управляющую последовательность или условную управляющую последовательность, неправильна.

(начиная с C++26)

[править] Примечание

Строковые литералы можно использовать для инициализации массивов символов. Если массив инициализируется как char str[] = "foo";, str будет содержать копию строки "foo".

Строковые литералы можно конвертировать и присваивать неконстантным char* или wchar_t* для совместимости с C, где строковые литералы имеют типы char[N] и wchar_t[N]. Такое неявное преобразование устарело.

(до C++11)

Строковые литералы нельзя конвертировать или присваивать неконстантным CharT*. Если такое преобразование требуется, необходимо использовать явное приведение (например, const_cast).

(начиная с 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. неправильно сформировано, если
    кодовые единицы не могут быть
    представлены в целочисленном
    типе без знака, соответствующему
    базовому типу
  1. 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 по Строковые литералы