Namespaces
Variants

String literals

From cppreference.net

Konstruiert ein unbenanntes Objekt eines bestimmten Zeichenarray-Typs direkt an Ort und Stelle, verwendet wenn ein Zeichenstring im Quellcode eingebettet werden muss.

Inhaltsverzeichnis

Syntax

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

wo

s-char-sequence - null oder mehr Zeichen, von denen jedes entweder ein Multibyte-Zeichen aus dem Quellzeichensatz (ausgenommen ( " ), \ und Zeilenumbruch) oder Zeichen-Escape, Hex-Escape, Oktal-Escape oder universeller Zeichenname (seit C99) ist, wie definiert in Escape-Sequenzen .
1) Zeichenkettenliteral : Der Typ des Literals ist char [ N ] , wobei N die Größe der Zeichenkette in Codeeinheiten der ausgeführten schmalen Kodierung ist, einschließlich des Nullterminators. Jedes char -Element im Array wird aus dem nächsten Zeichen in s-char-sequence unter Verwendung des Ausführungszeichensatzes initialisiert.
2) UTF-8-Stringliteral : Der Typ des Literals ist char [ N ] (bis C23) char8_t [ N ] (seit C23) , wobei N die Größe des Strings in UTF-8-Codeeinheiten inklusive des Nullterminators ist. Jedes char (bis C23) char8_t (seit C23) -Element im Array wird aus dem nächsten Multibyte-Zeichen in der s-char-sequence unter Verwendung von UTF-8-Kodierung initialisiert.
3) 16-Bit-Breite Zeichenkette: Der Typ des Literals ist char16_t [ N ] , wobei N die Größe der Zeichenkette in Codeeinheiten einer implementierungsdefinierten 16-Bit-Codierung (typischerweise UTF-16) ist, einschließlich des Nullterminators. Jedes char16_t -Element im Array wird initialisiert, als ob mbrtoc16 in einem implementierungsdefinierten Locale ausgeführt würde.
4) 32-Bit-Breite Zeichenkette: Der Typ des Literals ist char32_t [ N ] , wobei N die Größe der Zeichenkette in Codeeinheiten einer implementierungsdefinierten 32-Bit-Codierung (typischerweise UTF-32) ist, einschließlich des Nullterminators. Jedes char32_t -Element im Array wird initialisiert, als ob mbrtoc32 in einem implementierungsdefinierten Locale ausgeführt würde.
(bis C23)
3) UTF-16-Zeichenkettenliteral : Der Typ des Literals ist char16_t [ N ] , wobei N die Größe der Zeichenkette in UTF-16-Codeeinheiten einschließlich des Nullterminators ist. Jedes char16_t -Element im Array wird aus dem nächsten Multibyte-Zeichen in s-char-sequence unter Verwendung von UTF-16-Codierung initialisiert.
4) UTF-32-Zeichenkettenliteral : Der Typ des Literals ist char32_t [ N ] , wobei N die Größe der Zeichenkette in UTF-32-Codeeinheiten einschließlich des Nullterminators ist. Jedes char32_t -Element im Array wird aus dem nächsten Multibyte-Zeichen in s-char-sequence unter Verwendung von UTF-32-Codierung initialisiert.
(seit C23)
5) Breitzeichenkettenliteral: Der Typ des Literals ist wchar_t [ N ] , wobei N die Größe der Zeichenkette in Codeeinheiten der Ausführungs-Breitzeichenkodierung ist, einschließlich des Nullterminators. Jedes wchar_t -Element im Array wird initialisiert, als ob durch Ausführung von mbstowcs im implementierungsdefinierten Locale.

Erklärung

Zunächst werden in Übersetzungsphase 6 (nach der Makroersetzung) die benachbarten String-Literale (d.h. String-Literale, die nur durch Leerzeichen getrennt sind) verkettet.

Es dürfen nur zwei schmale oder zwei breite Zeichenkettenliterale verkettet werden.

(until C99)

Wenn ein Literal kein Präfix hat, erhält das resultierende Zeichenkettenliteral die Breite/Kodierung, die durch das präfixierte Literal spezifiziert wird.

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

Wenn die beiden Zeichenkettenliterale unterschiedliche Kodierungspräfixe haben, ist die Verkettung implementierungsdefiniert, außer dass ein UTF-8-Zeichenkettenliteral und ein Breitzeichenkettenliteral nicht verkettet werden können.

(since C11)
(until C23)

Wenn die beiden Zeichenkettenliterale unterschiedliche Kodierungspräfixe haben, ist die Verkettung fehlerhaft.

(since C23)

Zweitens wird in Übersetzungsphase 7 ein abschließendes Nullzeichen zu jedem String-Literal hinzugefügt, und dann initialisiert jedes Literal ein unbenanntes Array mit statischer Speicherdauer und einer Länge, die gerade ausreicht, um den Inhalt des String-Literals plus eins für den Null-Terminator zu enthalten.

char* p = "\x12" "3"; // erzeugt ein statisches char[3]-Array mit {'\x12', '3', '\0'}
                      // setzt p auf das erste Element des Arrays

String-Literale sind nicht veränderbar (und können tatsächlich in schreibgeschützten Speicherbereichen wie .rodata abgelegt werden). Wenn ein Programm versucht, das statische Array zu modifizieren, das durch ein String-Literal gebildet wird, ist das Verhalten undefiniert.

char* p = "Hello";
p[1] = 'M'; // Undefiniertes Verhalten
char a[] = "Hello";
a[1] = 'M'; // OK: a ist kein String-Literal

Es ist weder erforderlich noch verboten, dass identische String-Literale auf denselben Speicherort verweisen. Darüber hinaus können sich überlappende String-Literale oder String-Literale, die Teilzeichenketten anderer String-Literale sind, kombiniert werden.

"def" == 3+"abcdef"; // kann 1 oder 0 sein, implementierungsdefiniert

Hinweise

Ein String-Literal ist nicht notwendigerweise ein String; wenn ein String-Literal eingebettete Nullzeichen enthält, repräsentiert es ein Array, das mehr als einen String enthält:

char* p = "abc\0def"; // strlen(p) == 3, aber das Array hat die Größe 8

Wenn auf eine hexadezimale Escape-Sequenz in einem String-Literal eine gültige Hex-Ziffer folgt, würde dies zu einem Kompilierungsfehler aufgrund einer ungültigen Escape-Sequenz führen, jedoch kann String-Konkatenation als Workaround verwendet werden:

//char* p = "\xfff"; // Fehler: Hexadezimale Escape-Sequenz außerhalb des gültigen Bereichs
char* p = "\xff""f"; // Korrekt, das Literal ist char[3] mit {'\xff', 'f', '\0'}

String-Literale können verwendet werden, um Arrays zu initialisieren , und wenn die Größe des Arrays um eins kleiner ist als die Größe des String-Literals, wird der Null-Terminator ignoriert:

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

Die Kodierung von Zeichenkettenliteralen (1) und Breitzeichenkettenliteralen (5) ist implementierungsdefiniert. Beispielsweise wählt gcc diese mit den Kommandozeilenoptionen - fexec - charset und - fwide - exec - charset aus.

Obwohl die Verkettung gemischter Breitzeichen-Zeichenkettenliterale in C11 erlaubt ist, lehnen fast alle Compiler eine solche Verkettung ab (die einzige bekannte Ausnahme ist SDCC ), und ihre Verwendungserfahrung ist unbekannt. Infolgedessen wird die Zulassung der Verkettung gemischter Breitzeichen-Zeichenkettenliterale in C23 entfernt.

Beispiel

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

Mögliche Ausgabe:

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

Referenzen

  • C23-Standard (ISO/IEC 9899:2024):
  • 6.4.5 Stringliterale (S.: TBD)
  • C17-Standard (ISO/IEC 9899:2018):
  • 6.4.5 Stringliterale (S: 50-52)
  • C11-Standard (ISO/IEC 9899:2011):
  • 6.4.5 Zeichenkettenliterale (S. 70-72)
  • C99-Standard (ISO/IEC 9899:1999):
  • 6.4.5 Zeichenkettenliterale (S: 62-63)
  • C89/C90 Standard (ISO/IEC 9899:1990):
  • 3.1.4 Zeichenkettenliterale

Siehe auch

C++ Dokumentation für String-Literal