Literales de cadena y carácter (C++)

C++ admite varios tipos de cadenas y caracteres, y proporciona maneras de expresar valores literales de cada uno de esos tipos. En el código fuente, el contenido de los literales de carácter y cadena se expresa mediante un juego de caracteres. Los nombres de carácter universal y los caracteres de escape permiten expresar cualquier cadena con tan solo el juego básico de caracteres de código fuente. Un literal de cadena sin formato permite evitar la utilización de caracteres de escape y puede usarse para expresar todos los tipos de literales de cadena. También se pueden crear literales std::string sin necesidad de seguir pasos adicionales de construcción o conversión.

#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
}

Los literales de cadena no tienen prefijos o tienen los prefijos u8, L, u y U para denotar caracteres estrechos (byte único o multibyte), UTF-8, caracteres anchos (UCS-2 o UTF-16), codificaciones UTF-16 y UTF-32, respectivamente. Un literal de cadena sin formato puede tener los prefijos R, u8R, LR, uR y UR para los equivalentes sin formato de estas codificaciones. Para crear valores std::string temporales o estáticos, puede usar literales de cadena o literales de cadena sin formato con un sufijo s. Para obtener más información, consulte la sección Literales de cadena a continuación. Para obtener más información sobre el juego básico de caracteres de código fuente, los nombres de carácter universal y el uso de caracteres para páginas de códigos extendidas en el código fuente, consulte Juego de caracteres.

Literales de carácter

Un literal de carácter está compuesto por un carácter de constante. Se representa mediante el carácter delimitado por comillas simples. Hay cinco tipos de literales de carácter:

  • Literales de caracteres ordinarios de tipo char (por ejemplo, 'a')

  • Literales de caracteres UTF-8 de tipo char (char8_t en C++20), por ejemplo u8'a'

  • Literales de caracteres anchos de tipo wchar_t(por ejemplo, L'a')

  • Literales de caracteres UTF-16 de tipo char16_t (por ejemplo, u'a')

  • Literales de caracteres UTF-32 de tipo char32_t (por ejemplo, U'a')

El carácter que se usa para un literal de carácter puede ser cualquier carácter, a excepción de los caracteres reservados como la barra diagonal inversa (\), las comillas simples (') o la nueva línea. Los caracteres reservados se pueden especificar mediante una secuencia de escape. Los caracteres se pueden especificar mediante nombres de carácter universal, siempre que el tipo sea lo suficientemente grande como para contener al carácter.

Encoding

Los literales de caracteres se codifican de forma diferente en función de su prefijo.

  • Un literal de carácter sin prefijo es un literal de carácter normal. El valor de un literal de carácter normal que contiene un solo carácter, una secuencia de escape o un nombre de carácter universal que se puede representar en el juego de caracteres de ejecución tiene un valor igual al valor numérico de su codificación en el juego de caracteres de ejecución. Un literal de carácter normal que contiene más de un carácter, una secuencia de escape o un nombre de carácter universal es un literal multicaracter. Un literal multicaracter o un literal de carácter normal que no se puede representar en el juego de caracteres de ejecución tiene el tipo int y su valor está definido por la implementación. Para MSVC, consulte la sección específica de Microsoft más adelante.

  • Un literal de carácter que comienza con el prefijo L es un literal de caracteres anchos. El valor de un literal de caracteres anchos que contiene un solo carácter, secuencia de escape o nombre de carácter universal tiene un valor igual al valor numérico de su codificación en el juego de caracteres anchos de ejecución a menos que el literal de caracteres no tenga ninguna representación en el juego de caracteres anchos de ejecución, en cuyo caso el valor está definido por la implementación. El valor de un literal de caracteres anchos que contiene varios caracteres, secuencias de escape o nombres de caracteres universales está definido por la implementación. Para MSVC, consulte la sección específica de Microsoft más adelante.

  • Un literal de carácter que comienza con el prefijo u8 es un literal de caracteres UTF-8. El valor de un literal de caracteres UTF-8 que contiene un solo carácter, secuencia de escape o nombre de carácter universal tiene un valor igual a su valor de punto de código ISO 10646 si se puede representar mediante una sola unidad de código UTF-8 (correspondiente al bloque C0 Controls y Basic Latin Unicode). Si el valor no se puede representar mediante una sola unidad de código UTF-8, el programa tiene un formato incorrecto. Un literal de caracteres UTF-8 que contiene más de un carácter, secuencia de escape o nombre de carácter universal no tiene formato.

  • Un literal de carácter que comienza con el prefijo u es un literal de caracteres UTF-16. El valor de un literal de caracteres UTF-16 que contiene un solo carácter, secuencia de escape o nombre de carácter universal tiene un valor igual a su valor de punto de código ISO 10646 si se puede representar mediante una sola unidad de código UTF-16 (correspondiente al plano multilingüe básico). Si el valor no se puede representar mediante una sola unidad de código UTF-16, el programa tiene un formato incorrecto. Un literal de caracteres UTF-16 que contiene más de un carácter, secuencia de escape o nombre de carácter universal no tiene formato.

  • Un literal de carácter que comienza con el prefijo U es un literal de caracteres UTF-32. El valor de un literal de caracteres UTF-32 que contiene un solo carácter, secuencia de escape o nombre de carácter universal tiene un valor igual a su valor de punto de código ISO 10646. Un literal de caracteres UTF-32 que contiene más de un carácter, secuencia de escape o nombre de carácter universal no tiene formato.

Secuencias de escape

Hay tres tipos de secuencias de escape: simple, octal, hexadecimal. Las secuencias de escape pueden ser cualquiera de los siguientes valores:

Valor Secuencia de escape
Nueva línea \n
barra diagonal inversa \\
Tabulación horizontal \t
signo de interrogación ? ¿O\?
Tabulación vertical \v
comillas simples \'
retroceso \b
Comilla doble \"
retorno de carro \r
Carácter nulo \0
avance de página \f
Octal \ooo
Alerta (campana) \a
Hexadecimal \xhhh

Una secuencia de escape octal es una barra diagonal inversa seguida de una secuencia de uno a tres dígitos octales. Una secuencia de escape octal finaliza en el primer carácter que no es un dígito octal, si se encuentra antes que el tercer dígito. El valor octal más alto posible es \377.

Una secuencia de escape hexadecimal es una barra diagonal inversa seguida del carácter x y seguida de una secuencia de uno o varios dígitos hexadecimales. Los ceros a la izquierda se ignoran. En un literal de carácter estrecho sin prefijo o con prefijo u8, el valor hexadecimal máximo es 0xFF. En un literal de carácter ancho con prefijo L o prefijo u, el valor hexadecimal máximo es 0xFFFF. En un literal de carácter ancho con prefijo U, el valor hexadecimal máximo es 0xFFFFFFFF.

En este código de ejemplo se muestran algunos ejemplos de caracteres de escape mediante literales de caracteres normales. La misma sintaxis de secuencia de escape es válida para los demás tipos literales de caracteres.

#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
*/

El carácter de barra diagonal inversa (\) es un carácter de continuación de línea cuando se coloca al final de una línea. Si quiere que un carácter de barra diagonal inversa aparezca como un literal de carácter, debe escribir dos barras diagonales inversas en una fila (\\). Para obtener más información sobre el carácter de continuación de línea, consulte Phases of Translation.

Específico de Microsoft

Para crear un valor a partir de un literal multicaracter estrecho, el compilador convierte el carácter o la secuencia de caracteres entre comillas simples en valores de ocho bits dentro de un entero de 32 bits. Varios caracteres del literal rellenan los bytes correspondientes según sea necesario de orden superior a orden inferior. A continuación, el compilador convierte el entero en el tipo de destino siguiendo las reglas habituales. For ejemplo, para crear un valor char, el compilador usa el byte de orden inferior. Para crear un valor wchar_t o char16_t , el compilador usa la palabra de orden inferior. El compilador advierte que el resultado se trunca si cualquiera de los bits se establece por encima del byte o la palabra asignados.

char c0    = 'abcd';    // C4305, C4309, truncates to 'd'
wchar_t w0 = 'abcd';    // C4305, C4309, truncates to '\x6364'
int i0     = 'abcd';    // 0x61626364

Una secuencia de escape octal que parece contener más de tres dígitos se trata como una secuencia octal de 3 dígitos, seguida de los dígitos posteriores como caracteres en un literal multicaracter, lo que puede dar resultados sorprendentes. Por ejemplo:

char c1 = '\100';   // '@'
char c2 = '\1000';  // C4305, C4309, truncates to '0'

Las secuencias de escape que parecen contener caracteres que no son octales se evalúan como una secuencia octal hasta el último carácter octal, seguido del resto de los caracteres como caracteres posteriores en un literal multicaracter. Advertencia C4125 se genera si el primer carácter no octal es un dígito decimal. Por ejemplo:

char c3 = '\009';   // '9'
char c4 = '\089';   // C4305, C4309, truncates to '9'
char c5 = '\qrs';   // C4129, C4305, C4309, truncates to 's'

Secuencia de escape octal que tiene un valor mayor que \377 causa el error C2022: 'value-in-decimal': demasiado grande para el carácter.

Una secuencia de escape que parece tener caracteres hexadecimales y no hexadecimales se evalúa como un literal multicaracter que contiene una secuencia de escape hexadecimal hasta el último carácter hexadecimal, seguido de los caracteres no hexadecimales. Una secuencia de escape hexadecimal que no contiene ningún dígito hexadecimal produce el error del compilador C2153: “los literales hexadecimales deben tener al menos un dígito hexadecimal”.

char c6 = '\x0050'; // 'P'
char c7 = '\x0pqr'; // C4305, C4309, truncates to 'r'

Si un literal de caracteres anchos con prefijo L contiene una secuencia de varios caracteres, el valor se toma del primer carácter y el compilador genera la advertencia C4066. Los caracteres subsiguientes se ignoran, a diferencia del comportamiento que se observa en el literal multicaracter ordinario equivalente.

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

La sección específica de Microsoft termina aquí.

nombres de carácter universal

En los literales de carácter y los literales de cadena nativa (con formato), se puede representar cualquier carácter mediante un nombre de carácter universal. Los nombres de carácter universal se forman con un prefijo \U seguido de un punto de código Unicode de ocho dígitos o con un prefijo \u seguido de un punto de código Unicode de cuatro dígitos. La totalidad de los dígitos (ocho o cuatro, respectivamente) debe estar presente para formar un nombre de carácter universal correctamente.

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'

Pares suplentes

Los nombres de carácter universal no pueden codificar valores que se encuentran en el rango de punto de código suplente de D800 a DFFF. En el caso de pares suplentes Unicode, especifique el nombre de carácter universal mediante \UNNNNNNNN, donde NNNNNNNN es el punto de código de ocho dígitos para el carácter. El compilador genera un par suplente si es necesario.

En C++03, el lenguaje solo permitía representar un subconjunto de caracteres mediante sus nombres de caracteres universales y permitía algunos nombres de caracteres universales que realmente no representaban ningún carácter Unicode válido. Este error se corrigió en el estándar de C++11. En C++11, tanto los literales de carácter y cadena como los identificadores pueden usar nombres de carácter universal. Para obtener más información sobre los nombres de carácter universal, consulte Character Sets. Para obtener más información sobre Unicode, consulte Unicode. Para obtener más información sobre los pares suplentes, consulte Pares suplentes y caracteres complementarios.

Literales de cadena

Un literal de cadena representa una secuencia de caracteres que, en conjunto, forman una cadena terminada en null. Los caracteres deben escribirse entre comillas. Hay los siguientes tipos de literales de cadena:

Literales de cadena estrechos

Un literal de cadena estrecho es una matriz sin prefijo, delimitada por comillas dobles y terminada en null del tipo const char[n], donde n es la longitud de la matriz en bytes. Un literal de cadena estrecho puede contener cualquier carácter gráfico, excepto las comillas dobles ("), la barra diagonal inversa (\) o el carácter de nueva línea (\n). Un literal de cadena estrecho también puede contener las secuencias de escape antes mencionadas, así como nombres de carácter universal que caben en un byte.

const char *narrow = "abcd";

// represents the string: yes\no
const char *escaped = "yes\\no";

Cadenas con codificación UTF-8

Una cadena con codificación UTF-8 es una matriz con prefijo u8, delimitada por comillas dobles y terminada en null del tipo const char[n], donde n es la longitud de la matriz codificada en bytes. Un literal de cadena con prefijo u8 puede tener cualquier carácter gráfico, excepto las comillas dobles ("), la barra diagonal inversa (\) o el carácter de nueva línea (\n). También puede contener las secuencias de escape de secuencias antes mencionadas y cualquier nombre de carácter universal.

C++20 presenta el tipo de carácter portátil char8_t (Unicode codificado con UTF-8) de 8 bits. En C++20, los prefijos literales u8 especifican caracteres o cadenas de char8_t en lugar de 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:-)";

Literales de cadena anchos

Un literal de cadena ancho es una matriz terminada en null de valores wchar_t constantes que lleva el prefijo 'L' y que contiene cualquier carácter gráfico excepto las comillas dobles ("), la barra diagonal inversa (\) o el carácter de nueva línea. También puede contener las secuencias de escape de secuencias antes mencionadas y cualquier nombre de carácter universal.

const wchar_t* wide = L"zyxw";
const wchar_t* newline = L"hello\ngoodbye";

char16_t y char32_t (C++11)

C ++ 11 incluye los tipos de caracteres portables char16_t (Unicode de 16 bits) y char32_t (32 bits Unicode):

auto s3 = u"hello"; // const char16_t*
auto s4 = U"hello"; // const char32_t*

Literales de cadena sin formato (C++11)

Un literal de cadena sin formato es una matriz terminada en null (de cualquier tipo de carácter) que contiene cualquier carácter gráfico, incluidas las comillas dobles ("), la barra diagonal inversa (\) o el carácter de nueva línea. Los literales de cadena sin formato suelen usarse en expresiones regulares que utilizan clases de caracteres, y en las cadenas HTML y XML. Para obtener ejemplos, vea el siguiente artículo: preguntas más frecuentes de Bjarne Stroustrup sobre 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)";

Un delimitador es una secuencia definida por el usuario de hasta 16 caracteres que precede inmediatamente al paréntesis de apertura de un literal de cadena sin formato, y sigue inmediatamente a su paréntesis de cierre. Por ejemplo, en R"abc(Hello"\()abc" la secuencia de delimitador es abc y el contenido de la cadena es Hello"\(. Puede usar un delimitador para eliminar la ambigüedad de las cadenas sin formato que contienen comillas dobles y paréntesis. Este literal de cadena produce un error del compilador:

// meant to represent the string: )"
const char* bad_parens = R"()")";  // error C2059

Pero un delimitador lo resuelve:

const char* good_parens = R"xyz()")xyz";

Puede construir un literal de cadena sin formato que contiene una línea nueva (no el carácter de escape) en el código fuente:

// represents the string: hello
//goodbye
const wchar_t* newline = LR"(hello
goodbye)";

Literales std::string (C++14)

Los literales std::string son implementaciones de la biblioteca estándar de literales definidos por el usuario (véase abajo) que se representan como "xyz"s (con un sufijo s). Este tipo de literal de cadena produce un objeto temporal de tipo std::string, std::wstring, std::u32string o std::u16string según el prefijo que se especifique. Cuando no se usa ningún prefijo, como en el caso de arriba, se genera un std::string. L"xyz"s genera un std::wstring. u"xyz"s produce un std::u16string y U"xyz"s produce un 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 };

El sufijo s también puede usarse en literales de cadena sin formato:

u32string str6{ UR"(She said "hello.")"s };

Los literales std::string se definen en el espacio de nombres std::literals::string_literals del archivo de encabezado <string>. Dado que tanto std::literals::string_literalscomo std::literals se declaran como espacios de nombres alineados, std::literals::string_literals se trata automáticamente como si perteneciera directamente al espacio de nombres std.

Tamaño de literales de cadena

En cadenas char* de ANSI y otras codificaciones de byte único (pero no UTF-8), el tamaño (en bytes) de un literal de cadena es el número de caracteres más uno (para el carácter nulo de terminación). En el resto de los tipos de cadena, el tamaño no está estrictamente relacionado con el número de caracteres. UTF-8 usa hasta cuatro elementos char para codificar algunas unidades de código; char16_t o wchar_t codificados como UTF-16 pueden usar dos elementos (para un total de cuatro bytes) para codificar una única unidad de código. En este ejemplo se muestra el tamaño, en bytes, de un literal de cadena ancho:

const wchar_t* str = L"Hello!";
const size_t byteSize = (wcslen(str) + 1) * sizeof(wchar_t);

Observe que strlen() y wcslen() no incluyen el tamaño del carácter nulo de terminación, cuyo tamaño es igual que el tamaño del elemento del tipo string: un byte en una cadena de char* o char8_t*, dos bytes en cadenas wchar_t* o char16_t* y cuatro bytes en cadenas de char32_t*.

En versiones anteriores a Visual Studio 2022, versión 17.0, la longitud máxima de un literal de cadena es de 65 535 bytes. Este límite se aplica a los literales de cadena estrechos y anchos. En Visual Studio 2022, versión 17.0 y posteriores, esta restricción se suprime y la longitud de cadena la limitan los recursos disponibles.

Modificación de literales de cadena

Dado que los literales de cadena son constantes (a excepción de los literales std::string), intentar modificarlos (por ejemplo, str[2] = 'A') provoca un error del compilador.

Específico de Microsoft

En Microsoft C++, puede utilizar un literal de cadena para inicializar un puntero a char o a wchar_tno constantes. Esta inicialización no const se permite en el código C99, pero está en desuso en C++98 y se eliminó en C++11. Un intento de modificar la cadena produce una infracción de acceso, como en este ejemplo:

wchar_t* str = L"hello";
str[2] = L'a'; // run-time error: access violation

Puede hacer que el compilador emita un error cuando un literal de cadena se convierte en un puntero de carácter non-const al establecer la opción del compilador /Zc:strictStrings(Disable string literal type conversion). Es recomendable para el código portable que cumple los estándares. También es conveniente usar la palabra clave auto para declarar punteros inicializados de literales de cadena, porque resuelve el tipo (const) correcto. Por ejemplo, en este ejemplo de código se detecta un intento de escribir en un literal de cadena en tiempo de compilación:

auto str = L"hello";
str[2] = L'a'; // C3892: you cannot assign to a variable that is const.

En algunos casos, pueden agruparse literales de cadena idénticos para ahorrar espacio en el archivo ejecutable. En la agrupación de literales de cadena, el compilador hace que todas las referencias a un literal de cadena determinado apunten a la misma ubicación de la memoria, en lugar de apuntar cada una a una instancia distinta del literal de cadena. Para habilitar la agrupación de cadenas, use la opción del compilador /GF.

La sección específica de Microsoft termina aquí.

Concatenación de literales de cadena adyacentes

Los literales de cadena anchos o estrechos adyacentes se concatenan. Esta declaración:

char str[] = "12" "34";

es idéntica a esta declaración:

char atr[] = "1234";

y a esta declaración:

char atr[] =  "12\
34";

El uso de códigos de escape hexadecimales insertados para especificar literales de cadena puede producir resultados inesperados. El ejemplo siguiente está pensado para crear un literal de cadena que contiene el carácter ASCII 5, seguido de los caracteres f, i, v y e:

"\x05five"

El resultado real es 5F hexadecimal, que es el código ASCII de un carácter de subrayado, seguido de los caracteres i, v y e. Para obtener el resultado correcto, puede utilizar una de estas secuencia de escape:

"\005five"     // Use octal literal.
"\x05" "five"  // Use string splicing.

Los literales std::string (y los relacionados std::u8string, std::u16stringy std::u32string) se pueden concatenar con el operador + definido para los tipos basic_string. También pueden concatenarse de la misma manera que literales de cadena adyacentes. En ambos casos, la codificación de cadena y el sufijo deben coincidir:

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

Literales de cadena con nombres de caracteres universales

Los literales de cadena nativos (con formato) pueden usar nombres de carácter universal para representar cualquier carácter, siempre que el nombre de carácter universal pueda codificarse como uno o varios caracteres en el tipo de cadena. Por ejemplo, no se puede codificar un nombre de carácter universal que representa un carácter extendido en una cadena de caracteres estrechos mediante la página de códigos ANSI, pero puede codificarse en cadenas de caracteres estrechos de algunas páginas de códigos multibyte, así como en cadenas UTF-8 o en una cadena de caracteres anchos. En C++11, los tipos de cadena char16_t* y char32_t* amplían la compatibilidad con Unicode y C++20 lo extiende al tipo 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-)";

Consulte también

Juegos de caracteres
Literales numéricos, booleanos y de puntero
Literales definidos por el usuario