Namespaces
Variants

String literals

From cppreference.net

Construye un objeto sin nombre de tipo de arreglo de caracteres especificado en el lugar, utilizado cuando una cadena de caracteres necesita estar incrustada en el código fuente.

Contenidos

Sintaxis

" s-char-sequence " (1)
u8" s-char-sequence " (2) (desde C11)
u" s-char-sequence " (3) (desde C11)
U" s-char-sequence " (4) (desde C11)
L" s-char-sequence " (5)

donde

s-char-sequence - cero o más caracteres, cada uno de los cuales es un carácter multibyte del conjunto de caracteres fuente (excluyendo ( " ), \ , y nueva línea), o secuencia de escape de carácter, secuencia de escape hexadecimal, secuencia de escape octal , o nombre de carácter universal (desde C99) como se define en secuencias de escape .
1) literal de cadena de caracteres : El tipo del literal es char [ N ] , donde N es el tamaño de la cadena en unidades de código de la codificación estrecha de ejecución, incluyendo el terminador nulo. Cada elemento char en el arreglo se inicializa desde el siguiente carácter en s-char-sequence usando el conjunto de caracteres de ejecución.
2) Literal de cadena UTF-8 : El tipo del literal es char [ N ] (hasta C23) char8_t [ N ] (desde C23) , donde N es el tamaño de la cadena en unidades de código UTF-8 incluyendo el terminador nulo. Cada elemento char (hasta C23) char8_t (desde C23) en el array se inicializa desde el siguiente carácter multibyte en s-char-sequence usando codificación UTF-8.
3) Literal de cadena ancha de 16 bits: El tipo del literal es char16_t [ N ] , donde N es el tamaño de la cadena en unidades de código de codificación de 16 bits definida por la implementación (típicamente UTF-16), incluyendo el terminador nulo. Cada elemento char16_t en el arreglo se inicializa como si se ejecutara mbrtoc16 en la configuración regional definida por la implementación.
4) Literal de cadena ancha de 32 bits: El tipo del literal es char32_t [ N ] , donde N es el tamaño de la cadena en unidades de código de codificación de 32 bits definida por la implementación (típicamente UTF-32), incluyendo el terminador nulo. Cada elemento char32_t en el arreglo se inicializa como si se ejecutara mbrtoc32 en la configuración regional definida por la implementación.
(hasta C23)
3) Literal de cadena UTF-16 : El tipo del literal es char16_t [ N ] , donde N es el tamaño de la cadena en unidades de código UTF-16 incluyendo el terminador nulo. Cada elemento char16_t en el arreglo se inicializa desde el siguiente carácter multibyte en s-char-sequence usando codificación UTF-16.
4) Literal de cadena UTF-32 : El tipo del literal es char32_t [ N ] , donde N es el tamaño de la cadena en unidades de código UTF-32 incluyendo el terminador nulo. Cada elemento char32_t en el arreglo se inicializa desde el siguiente carácter multibyte en s-char-sequence usando codificación UTF-32.
(desde C23)
5) literal de cadena ancha: El tipo del literal es wchar_t [ N ] , donde N es el tamaño de la cadena en unidades de código de la codificación ancha de ejecución, incluyendo el terminador nulo. Cada elemento wchar_t en el array se inicializa como si se ejecutara mbstowcs en una localización definida por la implementación.

Explicación

Primero, en la fase de traducción 6 (después de la expansión de macros), los literales de cadena adyacentes (es decir, literales de cadena separados únicamente por espacios en blanco) se concatenan.

Solo se pueden concatenar dos literales de cadena estrechos o dos anchos.

(until C99)

Si un literal no tiene prefijo, el literal de cadena resultante tiene el ancho/codificación especificado por el literal con prefijo.

L"Δx = %" PRId16 // at phase 4, PRId16 expands to "d"
                 // at phase 6, L"Δx = %" and "d" form L"Δx = %d"
(since C99)

Si los dos literales de cadena tienen prefijos de codificación diferentes, la concatenación está definida por la implementación, excepto que un literal de cadena UTF-8 y un literal de cadena ancha no pueden concatenarse.

(since C11)
(until C23)

Si los dos literales de cadena tienen prefijos de codificación diferentes, la concatenación está mal formada.

(since C23)

En segundo lugar, en la fase de traducción 7 , se añade un carácter nulo de terminación a cada literal de cadena, y luego cada literal inicializa un array sin nombre con duración de almacenamiento estática y longitud justa para contener el contenido del literal de cadena más uno para el terminador nulo.

char* p = "\x12" "3"; // crea un array char[3] estático que contiene {'\x12', '3', '\0'}
                      // establece p para que apunte al primer elemento del array

Los literales de cadena son no modificables (y de hecho pueden ubicarse en memoria de solo lectura como .rodata ). Si un programa intenta modificar el array estático formado por un literal de cadena, el comportamiento es indefinido.

char* p = "Hello";
p[1] = 'M'; // Comportamiento indefinido
char a[] = "Hello";
a[1] = 'M'; // OK: a no es un literal de cadena

No es requerido ni prohibido que los literales de cadena idénticos se refieran a la misma ubicación en memoria. Además, los literales de cadena superpuestos o los literales de cadena que son subcadenas de otros literales de cadena pueden combinarse.

"def" == 3+"abcdef"; // puede ser 1 o 0, definido por la implementación

Notas

Un literal de cadena no es necesariamente una cadena; si un literal de cadena tiene caracteres nulos incrustados, representa un arreglo que contiene más de una cadena:

char* p = "abc\0def"; // strlen(p) == 3, pero el array tiene tamaño 8

Si un dígito hexadecimal válido sigue a un escape hexadecimal en un literal de cadena, fallaría al compilar como una secuencia de escape inválida, pero se puede usar la concatenación de cadenas como solución alternativa:

//char* p = "\xfff"; // error: secuencia de escape hexadecimal fuera de rango
char* p = "\xff""f"; // correcto, el literal es char[3] que contiene {'\xff', 'f', '\0'}

Los literales de cadena pueden utilizarse para inicializar arrays , y si el tamaño del array es uno menos que el tamaño del literal de cadena, se ignora el terminador nulo:

char a1[] = "abc"; // a1 es char[4] que contiene {'a', 'b', 'c', '\0'}
char a2[4] = "abc"; // a2 es char[4] que contiene {'a', 'b', 'c', '\0'}
char a3[3] = "abc"; // a3 es char[3] que contiene {'a', 'b', 'c'}

La codificación de los literales de cadena de caracteres (1) y los literales de cadena anchos (5) está definida por la implementación. Por ejemplo, gcc los selecciona con las opciones de línea de comandos - fexec - charset y - fwide - exec - charset .

Aunque la concatenación de literales de cadena anchas mixtas está permitida en C11, casi todos los compiladores rechazan dicha concatenación (la única excepción conocida es SDCC ), y su experiencia de uso es desconocida. Como resultado, la permisividad de concatenación de literales de cadena anchas mixtas se elimina en C23.

Ejemplo

#include <inttypes.h>
#include <locale.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <uchar.h>
int main(void)
{
    char s1[] = "a猫🍌"; // or "a\u732B\U0001F34C"
#if __STDC_VERSION__ >= 202311L
    char8_t
#else
    char
#endif
    s2[] = u8"a猫🍌";
    char16_t s3[] = u"a猫🍌";
    char32_t s4[] = U"a猫🍌";
    wchar_t s5[] = L"a猫🍌";
    setlocale(LC_ALL, "en_US.utf8");
    printf("  \"%s\" is a char[%zu] holding     { ", s1, sizeof s1 / sizeof *s1);
    for(size_t n = 0; n < sizeof s1 / sizeof *s1; ++n)
        printf("0x%02X ", +(unsigned char)s1[n]);
    puts("}");
    printf(
#if __STDC_VERSION__ >= 202311L
    "u8\"%s\" is a char8_t[%zu] holding  { "
#else
    "u8\"%s\" is a char[%zu] holding     { "
#endif
, s2, sizeof s2 / sizeof *s2);
    for(size_t n = 0; n < sizeof s2 / sizeof *s2; ++n)
#if __STDC_VERSION__ >= 202311L
       printf("0x%02X ", s2[n]);
#else
       printf("0x%02X ", +(unsigned char)s2[n]);
#endif
    puts("}");
    printf(" u\"a猫🍌\" is a char16_t[%zu] holding { ", sizeof s3 / sizeof *s3);
    for(size_t n = 0; n < sizeof s3 / sizeof *s3; ++n)
       printf("0x%04" PRIXLEAST16" ", s3[n]);
    puts("}");
    printf(" U\"a猫🍌\" is a char32_t[%zu] holding { ", sizeof s4 / sizeof *s4);
    for(size_t n = 0; n < sizeof s4 / sizeof *s4; ++n)
       printf("0x%08" PRIXLEAST32" ", s4[n]);
    puts("}");
    printf(" L\"%ls\" is a wchar_t[%zu] holding  { ", s5, sizeof s5 / sizeof *s5);
    for(size_t n = 0; n < sizeof s5 / sizeof *s5; ++n)
       printf("0x%08X ", (unsigned)s5[n]);
    puts("}");
}

Salida posible:

  "a猫🍌" is a char[9] holding     { 0x61 0xE7 0x8C 0xAB 0xF0 0x9F 0x8D 0x8C 0x00 }
u8"a猫🍌" is a char[9] holding     { 0x61 0xE7 0x8C 0xAB 0xF0 0x9F 0x8D 0x8C 0x00 }
 u"a猫🍌" is a char16_t[5] holding { 0x0061 0x732B 0xD83C 0xDF4C 0x0000 }
 U"a猫🍌" is a char32_t[4] holding { 0x00000061 0x0000732B 0x0001F34C 0x00000000 }
 L"a猫🍌" is a wchar_t[4] holding  { 0x00000061 0x0000732B 0x0001F34C 0x00000000 }

Referencias

  • Estándar C23 (ISO/IEC 9899:2024):
  • 6.4.5 Literales de cadena (p: TBD)
  • Estándar C17 (ISO/IEC 9899:2018):
  • 6.4.5 Literales de cadena (p: 50-52)
  • Estándar C11 (ISO/IEC 9899:2011):
  • 6.4.5 Literales de cadena (p: 70-72)
  • Estándar C99 (ISO/IEC 9899:1999):
  • 6.4.5 Literales de cadena (p: 62-63)
  • Estándar C89/C90 (ISO/IEC 9899:1990):
  • 3.1.4 Literales de cadena

Véase también

Documentación de C++ para string literal