Namespaces
Variants

String literals

From cppreference.net

Construit un objet non nommé de type tableau de caractères spécifié en place, utilisé lorsqu'une chaîne de caractères doit être intégrée dans le code source.

Table des matières

Syntaxe

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

s-char-sequence - zéro ou plusieurs caractères, chacun étant soit un caractère multioctet de l'ensemble de caractères source (à l'exclusion de ( " ), \ , et du saut de ligne), soit une séquence d'échappement de caractère, séquence d'échappement hexadécimale, séquence d'échappement octale , ou nom de caractère universel (depuis C99) tel que défini dans les séquences d'échappement .
1) littéral de chaîne de caractères : Le type du littéral est char [ N ] , où N est la taille de la chaîne en unités de code de l'encodage étroit d'exécution, incluant le terminateur nul. Chaque élément char dans le tableau est initialisé à partir du caractère suivant dans la s-char-sequence en utilisant le jeu de caractères d'exécution.
2) Littéral de chaîne UTF-8 : Le type du littéral est char [ N ] (jusqu'en C23) char8_t [ N ] (depuis C23) , où N est la taille de la chaîne en unités de code UTF-8 incluant le terminateur nul. Chaque char (jusqu'en C23) char8_t (depuis C23) élément du tableau est initialisé à partir du prochain caractère multioctet dans s-char-sequence en utilisant l'encodage UTF-8.
3) Littéral de chaîne large 16 bits : Le type du littéral est char16_t [ N ] , où N est la taille de la chaîne en unités de code d'un encodage 16 bits défini par l'implémentation (généralement UTF-16), incluant le terminateur nul. Chaque élément char16_t dans le tableau est initialisé comme par exécution de mbrtoc16 dans une locale définie par l'implémentation.
4) Littéral de chaîne large 32 bits : Le type du littéral est char32_t [ N ] , où N est la taille de la chaîne en unités de code d'un encodage 32 bits défini par l'implémentation (généralement UTF-32), incluant le terminateur nul. Chaque élément char32_t dans le tableau est initialisé comme par exécution de mbrtoc32 dans une locale définie par l'implémentation.
(jusqu'à C23)
3) Littéral de chaîne UTF-16 : Le type du littéral est char16_t [ N ] , où N est la taille de la chaîne en unités de code UTF-16 incluant le terminateur nul. Chaque élément char16_t dans le tableau est initialisé à partir du prochain caractère multioctet dans s-char-sequence en utilisant l'encodage UTF-16.
4) Littéral de chaîne UTF-32 : Le type du littéral est char32_t [ N ] , où N est la taille de la chaîne en unités de code UTF-32 incluant le terminateur nul. Chaque élément char32_t dans le tableau est initialisé à partir du prochain caractère multioctet dans s-char-sequence en utilisant l'encodage UTF-32.
(depuis C23)
5) littéral de chaîne large : Le type du littéral est wchar_t [ N ] , où N est la taille de la chaîne en unités de code de l'encodage large d'exécution, incluant le terminateur nul. Chaque élément wchar_t dans le tableau est initialisé comme si en exécutant mbstowcs dans une locale définie par l'implémentation.

Explication

Premièrement, lors de la phase de traduction 6 (après l'expansion des macros), les littéraux de chaîne adjacents (c'est-à-dire les littéraux de chaîne séparés uniquement par des espaces) sont concaténés.

Seuls deux littéraux de chaîne étroits ou deux littéraux de chaîne larges peuvent être concaténés.

(jusqu'à C99)

Si un littéral n'est pas préfixé, le littéral de chaîne résultant a la largeur/encodage spécifié par le littéral préfixé.

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

Si les deux littéraux de chaîne ont des préfixes d'encodage différents, la concaténation est définie par l'implémentation, sauf qu'un littéral de chaîne UTF-8 et un littéral de chaîne large ne peuvent pas être concaténés.

(depuis C11)
(jusqu'à C23)

Si les deux littéraux de chaîne ont des préfixes d'encodage différents, la concaténation est mal formée.

(depuis C23)

Deuxièmement, lors de la phase de traduction 7 , un caractère nul de fin est ajouté à chaque littéral de chaîne, puis chaque littéral initialise un tableau non nommé avec une durée de stockage statique et une longueur juste suffisante pour contenir le contenu du littéral de chaîne plus un pour le terminateur nul.

char* p = "\x12" "3"; // crée un tableau statique char[3] contenant {'\x12', '3', '\0'}
                      // initialise p pour pointer vers le premier élément du tableau

Les littéraux de chaîne sont non modifiables (et peuvent en fait être placés en mémoire en lecture seule comme .rodata ). Si un programme tente de modifier le tableau statique formé par un littéral de chaîne, le comportement est indéfini.

char* p = "Hello";
p[1] = 'M'; // Comportement indéfini
char a[] = "Hello";
a[1] = 'M'; // OK : a n'est pas un littéral de chaîne

Il n'est ni requis ni interdit que des littéraux de chaîne identiques se réfèrent au même emplacement en mémoire. De plus, les littéraux de chaîne qui se chevauchent ou les littéraux de chaîne qui sont des sous-chaînes d'autres littéraux de chaîne peuvent être combinés.

"def" == 3+"abcdef"; // peut être 1 ou 0, défini par l'implémentation

Notes

Un littéral de chaîne n'est pas nécessairement une chaîne ; si un littéral de chaîne contient des caractères nuls incorporés, il représente un tableau qui contient plus d'une chaîne :

char* p = "abc\0def"; // strlen(p) == 3, mais le tableau a une taille de 8

Si un chiffre hexadécimal valide suit une séquence d'échappement hexadécimale dans un littéral de chaîne, cela entraînerait une erreur de compilation en raison d'une séquence d'échappement invalide, mais la concaténation de chaînes peut être utilisée comme solution de contournement :

//char* p = "\xfff"; // erreur : séquence d'échappement hexadécimale hors plage
char* p = "\xff""f"; // correct, le littéral est char[3] contenant {'\xff', 'f', '\0'}

Les littéraux de chaîne peuvent être utilisés pour initialiser des tableaux , et si la taille du tableau est inférieure d'un à la taille du littéral de chaîne, le terminateur nul est ignoré :

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

L'encodage des littéraux de chaîne de caractères (1) et des littéraux de chaîne larges (5) est défini par l'implémentation. Par exemple, gcc les sélectionne avec les options de ligne de commande - fexec - charset et - fwide - exec - charset .

Bien que la concaténation mixte de littéraux de chaîne larges soit autorisée en C11, presque tous les compilateurs rejettent une telle concaténation (la seule exception connue est SDCC ), et son expérience d'utilisation est inconnue. Par conséquent, l'autorisation de la concaténation mixte de littéraux de chaîne larges est supprimée en C23.

Exemple

#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("}");
}

Sortie possible :

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

Références

  • Norme C23 (ISO/CEI 9899:2024) :
  • 6.4.5 Littéraux de chaîne (p: TBD)
  • Norme C17 (ISO/CEI 9899:2018) :
  • 6.4.5 Littéraux de chaîne (p: 50-52)
  • Norme C11 (ISO/IEC 9899:2011):
  • 6.4.5 Littéraux de chaîne (p: 70-72)
  • Norme C99 (ISO/IEC 9899:1999) :
  • 6.4.5 Littéraux de chaîne (p: 62-63)
  • Norme C89/C90 (ISO/IEC 9899:1990) :
  • 3.1.4 Littéraux de chaîne

Voir aussi

Documentation C++ pour string literal