Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В C++ поддерживаются различные типы строк и символов, а также доступны различные способы выражения значений литералов каждого из этих типов. В исходном коде содержимое символьных и строковых литералов выражается с помощью набора символов. Универсальные имена символов и escape-символы позволяют представить любую строку, используя только основную кодировку исходного кода. Необработанные строковые литералы позволяют не использовать escape-символы и могут применяться для выражения всех типов строковых литералов. Вы также можете создавать std::string
литералы, не выполняя дополнительные шаги по созданию или преобразованию.
#include <string>
using namespace std::string_literals; // enables s-suffix for std::string literals
int main()
{
// Character literals
auto c0 = 'A'; // char
auto c1 = u8'A'; // char
auto c2 = L'A'; // wchar_t
auto c3 = u'A'; // char16_t
auto c4 = U'A'; // char32_t
// Multicharacter literals
auto m0 = 'abcd'; // int, value 0x61626364
// String literals
auto s0 = "hello"; // const char*
auto s1 = u8"hello"; // const char* before C++20, encoded as UTF-8,
// const char8_t* in C++20
auto s2 = L"hello"; // const wchar_t*
auto s3 = u"hello"; // const char16_t*, encoded as UTF-16
auto s4 = U"hello"; // const char32_t*, encoded as UTF-32
// Raw string literals containing unescaped \ and "
auto R0 = R"("Hello \ world")"; // const char*
auto R1 = u8R"("Hello \ world")"; // const char* before C++20, encoded as UTF-8,
// const char8_t* in C++20
auto R2 = LR"("Hello \ world")"; // const wchar_t*
auto R3 = uR"("Hello \ world")"; // const char16_t*, encoded as UTF-16
auto R4 = UR"("Hello \ world")"; // const char32_t*, encoded as UTF-32
// Combining string literals with standard s-suffix
auto S0 = "hello"s; // std::string
auto S1 = u8"hello"s; // std::string before C++20, std::u8string in C++20
auto S2 = L"hello"s; // std::wstring
auto S3 = u"hello"s; // std::u16string
auto S4 = U"hello"s; // std::u32string
// Combining raw string literals with standard s-suffix
auto S5 = R"("Hello \ world")"s; // std::string from a raw const char*
auto S6 = u8R"("Hello \ world")"s; // std::string from a raw const char* before C++20, encoded as UTF-8,
// std::u8string in C++20
auto S7 = LR"("Hello \ world")"s; // std::wstring from a raw const wchar_t*
auto S8 = uR"("Hello \ world")"s; // std::u16string from a raw const char16_t*, encoded as UTF-16
auto S9 = UR"("Hello \ world")"s; // std::u32string from a raw const char32_t*, encoded as UTF-32
}
Строковые литералы могут быть без префикса, или с префиксами u8
, L
, u
и U
, чтобы обозначать узкий символ (однобайтовый или многобайтовый), UTF-8, широкий символ (UCS-2 или UTF-16), кодировки UTF-16 и UTF-32 соответственно. Необработанный строковый литерал может иметь R
, u8R
и LR
uR
UR
префиксы для необработанных эквивалентов этих кодировок. Чтобы создать временные или статические std::string
значения, можно использовать строковые литералы или необработанные строковые литералы с суффиксом s
. Дополнительные сведения см. в разделе "Строковые литералы " ниже. Дополнительные сведения о базовом наборе исходных символов, универсальных именах символов и использовании символов из расширенных кодовых страниц в исходном коде см. в разделе "Наборы символов".
Символьные литералы
Символьный литерал состоит из символьной константы. Он представлен символом, окруженным одинарными кавычками. Существует пять типов символьных литерала:
Обычные символьные литералы типа
char
, например'a'
Символьные литералы UTF-8 типа
char
(char8_t
в C++20), напримерu8'a'
Расширенные символьные литералы типа
wchar_t
, напримерL'a'
.Типовые символьные литералы UTF-16, например
char16_t
,u'a'
Символьные литералы типа
char32_t
UTF-32, напримерU'a'
Символ, используемый для литерала символа, может быть любым символом, за исключением зарезервированных символов обратной косой черты (\
), одинарной кавычки ('
) или новой строки. Зарезервированные символы можно указывать с помощью escape-последовательности. Символы можно указывать с помощью универсальных имен символов, при условии что тип является достаточно крупным для размещения символа.
Кодировка
Литералы символов кодируются по-разному на основе префикса.
Символьный литерал без префикса — обычный символьный литерал. Значение обычного символьного литерала, содержащего один символ, escape-последовательность или универсальное имя символа, которое может быть представлено в наборе символов выполнения, имеет значение, равное числовому значению его кодировки в наборе символов выполнения. Обычный литерал символов, который содержит более одного символа, escape-последовательность или универсальное имя символа, называется многосимвольным литералом. Множественный литерал или обычный символьный литерал, который не может быть представлен в наборе символов выполнения, имеет тип
int
, и его значение определяется реализацией. Сведения о MSVC см. в разделе, относящемся к Microsoft, ниже.Символьный литерал, начинающийся с префикса
L
, — это широкий символьный литерал. Значение широкого символьного литерала, содержащего один символ, escape-последовательность или универсальное имя символов, имеет значение, равное числовому значению его кодировки в исполняемом наборе широких символов, если символьный литерал не имеет представления в исполняемом наборе широких символов, в этом случае значение определяется реализацией. Значение расширенных символьных литералов, содержащих несколько символов, escape-последовательностей или универсальных имен символов, определяется реализацией. Чтобы узнать о MSVC, см. раздел Microsoft-специфики ниже.Символьный литерал, начинающийся с
u8
префикса, — это символьный литерал UTF-8. Значение символьного литерала UTF-8, содержащего один символ, последовательность экранирования или универсальное название символа, совпадает со значением кодовой точки ISO 10646, если оно может быть представлено одним кодовым элементом UTF-8 (соответствующим блоку управляющих символов C0 и Basic Latin в Юникоде). Если значение не может быть представлено одним блоком кода UTF-8, программа не сформирована. Символьный литерал UTF-8, содержащий несколько символов, escape-последовательность или универсальное имя символов, является неправильно сформированным.Символьный литерал, начинающийся с префикса
u
, является символьным литералом UTF-16. Значение символьного литерала UTF-16, содержащего один символ, экранированную последовательность или универсальное имя символа, равно точке кода ISO 10646, если оно может быть представлено одной единицей кода UTF-16 (соответствующей базовой многоязычной плоскости). Если значение не может быть представлено одним блоком кода UTF-16, программа не сформирована. Литерал символа UTF-16, содержащий несколько символов, escape-последовательность или универсальное имя символов, является неправильно сформированным.Символьный литерал, начинающийся с
U
префикса, — это символьный литерал UTF-32. Значение символьного литерала UTF-32, содержащего один символ, последовательность экранирования или универсальное имя символа, равно значению точки кода ISO 10646. Символьный литерал UTF-32, содержащий несколько символов, escape-последовательность или универсальное имя символов, является неправильно сформированным.
Escape-последовательности
Существует три вида escape-последовательностей: простая, восьмеричная и шестнадцатеричная. Escape-последовательности могут представлять одно из следующих значений:
Значение | escape-последовательность |
---|---|
новая строка | \n |
обратная косая черта | \\ |
горизонтальная табуляция | \t |
вопросительный знак | ? или ? |
вертикальная табуляция | \v |
одинарная кавычка | \' |
BACKSPACE | \b |
двойная кавычка | \" |
Возврат каретки | \r |
нуль-символ | \0 |
Перевод страницы | \f |
восьмеричный | \ooo |
оповещение (колокольчик) | \a |
шестнадцатеричный | \xhhh |
Восьмеричная escape-последовательность — это обратная косая черта, за которой следует последовательность из одной до трех восьмеричных цифр. Восьмеричная escape-последовательность завершается на первом символе, который не является восьмеричной цифрой, если обнаружена раньше, чем третья цифра. Максимально возможное восьмеричное значение: \377
.
Шестнадцатеричная управляющая последовательность начинается с обратной косой черты, затем следует символ x
, а после него идет последовательность из одной или нескольких шестнадцатеричных цифр. Начальные нули пропускаются. В обычном или префиксном литерале символов u8 самое высокое шестнадцатеричное значение 0xFF. В расширенном символьном литерале с префиксом L или u максимальное шестнадцатеричное значение — 0xFFFF. В расширенном символьном литерале с префиксом U максимальное шестнадцатеричное значение — 0xFFFFFFFF.
В этом примере кода показаны некоторые примеры экранированных символов, используя обычные символьные литералы. Тот же синтаксис escape-последовательности действителен для других типов литеральных символов.
#include <iostream>
using namespace std;
int main() {
char newline = '\n';
char tab = '\t';
char backspace = '\b';
char backslash = '\\';
char nullChar = '\0';
cout << "Newline character: " << newline << "ending" << endl;
cout << "Tab character: " << tab << "ending" << endl;
cout << "Backspace character: " << backspace << "ending" << endl;
cout << "Backslash character: " << backslash << "ending" << endl;
cout << "Null character: " << nullChar << "ending" << endl;
}
/* Output:
Newline character:
ending
Tab character: ending
Backspace character:ending
Backslash character: \ending
Null character: ending
*/
Символ обратной косой черты (\
) — это символ продолжения строки, когда он помещается в конце строки. Если символ обратной косой черты требуется использовать как символьный литерал, необходимо ввести две косые черты подряд (\\
). Дополнительные сведения о символе продолжения строки см. в разделе Phases of Translation.
Только для систем Майкрософт
Чтобы создать значение из узкого многосимвольного литерала, компилятор преобразует последовательность символов между одинарными кавычками в 8-разрядные значения в 32-разрядное целое число. Несколько символов в литерале заполняют соответствующие байты по мере необходимости от высокого до низкого порядка. Затем компилятор преобразует целое число в тип назначения, следуя обычным правилам. Например, чтобы создать char
значение, компилятор принимает байт низкого порядка. Для создания значения wchar_t
или char16_t
компилятор принимает младшее слово. Компилятор выдает предупреждение о том, что результат усекается, если какие-либо биты заданы выше назначенного байта или слова.
char c0 = 'abcd'; // C4305, C4309, truncates to 'd'
wchar_t w0 = 'abcd'; // C4305, C4309, truncates to '\x6364'
int i0 = 'abcd'; // 0x61626364
Восьмеричная escape-последовательность, содержащая более трех цифр, оценивается как 3-значная октальная последовательность, за которой последующие цифры рассматриваются как символы в многосимвольном литерале, что может дать удивительные результаты. Например:
char c1 = '\100'; // '@'
char c2 = '\1000'; // C4305, C4309, truncates to '0'
Escape-последовательности, которые, как представляется, содержат неоктальные символы, оцениваются как восьмеричная последовательность до последнего октального символа, а затем оставшиеся символы рассматриваются как последующие символы в многохарактерном литерале. Предупреждение C4125 создается, если первый не восьмеричный символ является десятичной цифрой. Например:
char c3 = '\009'; // '9'
char c4 = '\089'; // C4305, C4309, truncates to '9'
char c5 = '\qrs'; // C4129, C4305, C4309, truncates to 's'
Восьмеричная escape-последовательность, которая имеет более высокое значение, чем \377
, вызывает ошибку C2022: 'value-in-decimal': слишком большое для символа.
Последовательность escape, которая, как представляется, имеет шестнадцатеричные и не шестнадцатеричные символы, оценивается как многосимвольный литерал, содержащий шестнадцатеричную escape-последовательность до последнего шестнадцатеричного символа, за которым следуют не шестнадцатеричные символы. Шестнадцатеричная escape-последовательность, не содержащая шестнадцатеричных цифр, вызывает ошибку компилятора C2153: "шестнадцатеричные литералы должны содержать хотя бы одну шестнадцатеричную цифру".
char c6 = '\x0050'; // 'P'
char c7 = '\x0pqr'; // C4305, C4309, truncates to 'r'
Если расширенный символьный литерал с префиксом L
содержит мультсимвольную последовательность, значение берется из первого символа, а компилятор вызывает предупреждение C4066. Последующие символы игнорируются, в отличие от поведения эквивалентного обычного многосимвольного литерала.
wchar_t w1 = L'\100'; // L'@'
wchar_t w2 = L'\1000'; // C4066 L'@', 0 ignored
wchar_t w3 = L'\009'; // C4066 L'\0', 9 ignored
wchar_t w4 = L'\089'; // C4066 L'\0', 89 ignored
wchar_t w5 = L'\qrs'; // C4129, C4066 L'q' escape, rs ignored
wchar_t w6 = L'\x0050'; // L'P'
wchar_t w7 = L'\x0pqr'; // C4066 L'\0', pqr ignored
Раздел , посвященный майкрософт , заканчивается здесь.
универсальные имена символов
В символьных литералах и машинных (не являющихся необработанными) строковых литералах любой символ может быть представлен универсальным именем символа. Универсальные имена символов формируются префиксом \U
, за которым следует восьмизначная кодовая точка Юникода или префикс \u
, за которым следует четырехзначная точка кода Юникода. Все восемь или четыре цифры, соответственно, должны присутствовать для создания правильного универсального имени символа.
char u1 = 'A'; // 'A'
char u2 = '\101'; // octal, 'A'
char u3 = '\x41'; // hexadecimal, 'A'
char u4 = '\u0041'; // \u UCN 'A'
char u5 = '\U00000041'; // \U UCN 'A'
Суррогатные пары
Универсальные имена символов не могут кодировать значения в диапазоне суррогатных точек кода D800-DFFF. Для суррогатных пар Юникода укажите универсальное имя символа, используя \UNNNNNNNN
, где NNNNNNNN — восьмизначная кодовая точка для символа. При необходимости компилятор создает суррогатную пару.
В C++03 язык допускает только подмножество символов, представленных их универсальными именами символов, и допускает некоторые универсальные имена символов, которые фактически не представляют допустимые символы Юникода. Эта ошибка была исправлена в стандарте C++11. В C++11 в символьных и строковых литералах и идентификаторах можно использовать универсальные имена символов. Дополнительные сведения об универсальных именах символов см. в разделе Character Sets. Дополнительные сведения о Юникоде см. в статье Unicode. Дополнительные сведения о суррогатных парах см. в статье Surrogate Pairs and Supplementary Characters(Суррогатные пары и дополнительные символы).
Строковые литералы
Строковый литерал представляет последовательность символов, которые вместе образуют строку, завершающуюся нулевым символом. Символы должны быть заключены в двойные кавычки. Существуют следующие типы строковых литералов.
Узкие строковые литералы
Узкий строковый литерал — это массив типа const char[n]
, без префикса, ограниченный двойными кавычками и с нулевым окончанием, где n — это длина массива в байтах. Обычный строковый литерал может содержать любые графические символы, за исключением двойных кавычек ("
), обратной косой черты (\
) или символа новой строки. Узкий строковый литерал также может содержать перечисленные выше escape-последовательности и универсальные имена символов, которые помещаются в байте.
const char *narrow = "abcd";
// represents the string: yes\no
const char *escaped = "yes\\no";
Строки в кодировке UTF-8
Строка в кодировке UTF-8 — это массив типа const char[n]
, с префиксом u8, ограниченный двойными кавычками и оканчивающийся на null, где n — длина закодированного массива в байтах. Строковый литерал с префиксом u8 может содержать любые графические символы, за исключением двойных кавычек ("
), обратной косой черты (\
) или символа новой строки. Строковый литерал с префиксом u8 может также содержать перечисленные выше escape-последовательности и любые универсальные имена символов.
C++20 представляет переносимый char8_t
(UTF-8 закодированный 8-разрядный тип символа Юникода). В C++20 префиксы литералов u8
обозначают символы или строки char8_t
вместо char
.
// Before C++20
const char* str1 = u8"Hello World";
const char* str2 = u8"\U0001F607 is O:-)";
// C++20 and later
const char8_t* u8str1 = u8"Hello World";
const char8_t* u8str2 = u8"\U0001F607 is O:-)";
Расширенные строковые литералы
Широкий строковый литерал — это массив констант wchar_t
, завершающийся символом null, префиксируемый "L
" и содержащий любой графический символ, кроме двойной кавычки ("
), обратной косой черты (\
) или символа новой строки. Расширенный строковый литерал может содержать перечисленные выше escape-последовательности и любые универсальные имена символов.
const wchar_t* wide = L"zyxw";
const wchar_t* newline = L"hello\ngoodbye";
char16_t и char32_t (C++11)
В C++11 доступны символьные типы char16_t
(портативный, 16-разрядный Юникод) и char32_t
(32-разрядный Юникод):
auto s3 = u"hello"; // const char16_t*
auto s4 = U"hello"; // const char32_t*
Необработанные строковые литералы (C++11)
Необработанный строковый литерал — это массив, завершающийся NULL, который состоит из графических символов любого типа, включая двойные кавычки ("
), обратную косую черту (\
) или символ новой строки. Необработанные строковые литералы часто применяются в регулярных выражениях, которые используют классы символов, а также в строках HTML и XML. Примеры см. в следующей статье: Bjarne Stroustrup's FAQ on C++11(Вопросы и ответы о C++11 от Бьерна Страуструпа).
// represents the string: An unescaped \ character
const char* raw_narrow = R"(An unescaped \ character)";
const wchar_t* raw_wide = LR"(An unescaped \ character)";
const char* raw_utf8a = u8R"(An unescaped \ character)"; // Before C++20
const char8_t* raw_utf8b = u8R"(An unescaped \ character)"; // C++20
const char16_t* raw_utf16 = uR"(An unescaped \ character)";
const char32_t* raw_utf32 = UR"(An unescaped \ character)";
Разделитель — это определяемая пользователем последовательность до 16 символов, которая непосредственно предшествует открытию круглых скобок необработанного строкового литерала и сразу же следует за закрывающей скобкой. Например, в R"abc(Hello"\()abc"
последовательность разделителей — abc
, а содержимое строки — Hello"\(
. Разделители можно использовать для различения необработанных строк, содержащих двойные кавычки и круглые скобки. Этот строковый литерал вызывает ошибку компилятора:
// meant to represent the string: )"
const char* bad_parens = R"()")"; // error C2059
Однако ошибку можно устранить с помощью разделителя:
const char* good_parens = R"xyz()")xyz";
Вы можете создать необработанный строковый литерал, содержащий новую строку (а не экранированный символ) в источнике:
// represents the string: hello
//goodbye
const wchar_t* newline = LR"(hello
goodbye)";
std::string строковые литералы (C++14)
std::string
литералы — это стандартные реализации определяемых пользователем литералов (см. ниже), представленные как "xyz"s
с суффиксом s
. Такой строковый литерал создает временный объект типа std::string
, std::wstring
std::u32string
или std::u16string
в зависимости от указанного префикса. Если префикс не используется, как описано выше, создается std::string
.
L"xyz"s
создает std::wstring
.
u"xyz"s
создает std::u16string, и U"xyz"s
создает std::u32string.
//#include <string>
//using namespace std::string_literals;
string str{ "hello"s };
string str2{ u8"Hello World" }; // Before C++20
u8string u8str2{ u8"Hello World" }; // C++20
wstring str3{ L"hello"s };
u16string str4{ u"hello"s };
u32string str5{ U"hello"s };
Суффикс s
можно также использовать в необработанных строковых литералах:
u32string str6{ UR"(She said "hello.")"s };
std::string
литералы определяются в пространстве std::literals::string_literals
имен в заголовочном файле <строка>. Поскольку std::literals::string_literals
и std::literals
объявляются как встроенные пространства имен, std::literals::string_literals
автоматически считается напрямую принадлежащим пространству имен std
.
Размер строковых литерала
Для строк ANSI char*
и других однобайтовых кодировок (но не UTF-8), размер (в байтах) строкового литерала — это число символов плюс 1 для завершающего символа NULL. Для всех других типов строк размер не связан строго с количеством символов. UTF-8 использует до четырех char
элементов для кодирования некоторых единиц кода и char16_t
wchar_t
в кодировке UTF-16 может использовать два элемента (в общей сложности четыре байта) для кодирования одной единицы кода. В примере ниже показан размер расширенного строкового литерала в байтах.
const wchar_t* str = L"Hello!";
const size_t byteSize = (wcslen(str) + 1) * sizeof(wchar_t);
Обратите внимание, что strlen()
и wcslen()
не включайте размер завершающего символа NULL, размер которого равен размеру элемента типа строки: один байт в char*
строке или char8_t*
строке, два байта wchar_t*
или char16_t*
строки и четыре байта в char32_t*
строках.
Максимальная длина строкового литерала после объединения:
- Visual Studio до версии 17.0 в 2022: максимальная длина строкового литерала после объединения составляет 65 535 байт. Это относится как к узким, так и к широким строковым литералам.
- Начиная с Visual Studio 2022 версии 17.0, максимальная длина строкового литерала после объединения ограничена только доступной памятью. Однако ограничение размера до объединения по-прежнему составляет 16 384 байта
Изменение строковых литералов
Так как строковые литералы (не включая std::string
литералы) являются константами, пытаясь изменить их( например, str[2] = 'A'
вызывает ошибку компилятора.
Только для систем Майкрософт
В Microsoft C++ можно использовать строковый литерал для инициализации указателя на неконстантный char
или wchar_t
. Эта неконстантная инициализация разрешена в коде C99, но устарела в C++98 и удалена в C++11. Попытка изменить строку вызовет нарушение прав доступа, как показано в следующем примере:
wchar_t* str = L"hello";
str[2] = L'a'; // run-time error: access violation
Вы можете заставить компилятор выдавать ошибку, когда строковый литерал преобразуется в указатель на неконстантный символ, установив параметр компилятора auto
для объявления указателей, инициализированных строковыми литералами, так как оно разрешает правильный (const) тип. В следующем примере кода перехватывается во время компиляции попытка записать в строковый литерал:
auto str = L"hello";
str[2] = L'a'; // C3892: you cannot assign to a variable that is const.
В некоторых случаях идентичные строковые литералы могут быть объединены в пул для экономии места в исполняемом файле. При объединении строковых литералов в пулы компилятор делает так, что все ссылки на определенный строковый литерал указывают на одну и ту же область в памяти, вместо того чтобы каждая ссылка указывала на отдельный экземпляр строкового литерала. Чтобы включить пул строк, используйте параметр компилятора /GF
.
Раздел , посвященный майкрософт , заканчивается здесь.
Сцепление смежных строковых литералов
Смежные широкие или узкие строковые литералы объединяются. Данная декларация
char str[] = "12" "34";
идентично следующему объявлению:
char atr[] = "1234";
и следующему объявлению:
char atr[] = "12\
34";
Использование внедренных шестнадцатеричных escape-кодов для задания строковых литералов может привести к непредвиденным результатам. В следующем примере выполняется попытка создать строковый литерал, содержащий символ ASCII 5, за которым следуют символы f, i, v и e:
"\x05five"
Фактический результат (шестнадцатеричное значение 5F) является кодом ASCII для символа подчеркивания, за которым следуют символы i, v и e. Чтобы получить правильный результат, можно использовать одну из следующих escape-последовательностей:
"\005five" // Use octal literal.
"\x05" "five" // Use string splicing.
std::string
литеральные значения, а также связанные std::u8string
, std::u16string
и std::u32string
, можно объединить с оператором +
, определённым для типов basic_string
. Их также можно сконкатенировать так же, как и соседние строковые литералы. В обоих случаях кодировка строки и суффикс должны совпадать:
auto x1 = "hello" " " " world"; // OK
auto x2 = U"hello" " " L"world"; // C2308: disagree on prefix
auto x3 = u8"hello" " "s u8"world"z; // C3688, disagree on suffixes
Строковые литералы с универсальными именами символов
Строковые литералы, не являющиеся необработанными, могут использовать универсальные имена символов для представления любого символа, если универсальные имена могут быть закодированы как один или несколько символов в данном типе строки. Например, универсальное имя символа, представляющее расширенный символ, не может быть закодировано в узкой строке с помощью кодовой страницы ANSI, но его можно закодировать в узких строках в некоторых многобайтовых кодовых страницах или в строках UTF-8 или в широкой строке. В C++11 поддержка Юникода расширяется типами строк char16_t*
и char32_t*
, а в C++20 поддержка увеличивается до типа char8_t
.
// ASCII smiling face
const char* s1 = ":-)";
// UTF-16 (on Windows) encoded WINKING FACE (U+1F609)
const wchar_t* s2 = L"😉 = \U0001F609 is ;-)";
// UTF-8 encoded SMILING FACE WITH HALO (U+1F607)
const char* s3a = u8"😇 = \U0001F607 is O:-)"; // Before C++20
const char8_t* s3b = u8"😇 = \U0001F607 is O:-)"; // C++20
// UTF-16 encoded SMILING FACE WITH OPEN MOUTH (U+1F603)
const char16_t* s4 = u"😃 = \U0001F603 is :-D";
// UTF-32 encoded SMILING FACE WITH SUNGLASSES (U+1F60E)
const char32_t* s5 = U"😎 = \U0001F60E is B-)";
См. также
Наборы символов
Числовые, логические и указательные литералы
Определяемые пользователем литералы