Namensräume
Varianten
Aktionen

Zeichenketten-Literale

Von cppreference.com
< c‎ | Sprache

Erstellt ein unbenanntes Objekt vom angegebenen Zeichentyp-Array "in-place", das verwendet wird, wenn eine Zeichenkette im Quellcode eingebettet werden muss.

Inhalt

[bearbeiten] 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)

wobei

s-char-sequence - Null oder mehr Zeichen, von denen jedes entweder ein Mehrbytezeichen aus dem Quellzeichensatz (ausschließlich ("), \ und Zeilenumbruch) oder eine Zeichenescape-Sequenz, eine Hexadezimal-Escape-Sequenz, eine Oktal-Escape-Sequenz, oder ein universeller Zeichenname(seit C99) ist, wie in Escape-Sequenzen definiert.
1) Zeichenkettenliteral: Der Typ des Literals ist char[N], wobei N die Größe der Zeichenkette in Code-Einheiten der schmalen Ausführungskodierung ist, einschließlich des Nullterminators. Jedes char-Element im Array wird aus dem nächsten Zeichen in s-char-sequence unter Verwendung des Ausführungskaricterzeichensatzes initialisiert.
2) UTF-8-Zeichenkettenliteral: Der Typ des Literals ist char[N](bis C23)char8_t[N](seit C23), wobei N die Größe der Zeichenkette in UTF-8-Code-Einheiten einschließlich des Nullterminators ist. Jedes char(bis C23)char8_t(seit C23)-Element im Array wird aus dem nächsten Mehrbytezeichen in s-char-sequence unter Verwendung der UTF-8-Kodierung initialisiert.
3) 16-Bit-Wide-Zeichenkettenliteral: Der Typ des Literals ist char16_t[N], wobei N die Größe der Zeichenkette in Code-Einheiten einer implementierungsdefinierten 16-Bit-Kodierung (typischerweise UTF-16) einschließlich des Nullterminators ist. Jedes char16_t-Element im Array wird initialisiert, als ob mbrtoc16 in einer implementierungsdefinierten Locale ausgeführt worden wäre.
4) 32-Bit-Wide-Zeichenkettenliteral: Der Typ des Literals ist char32_t[N], wobei N die Größe der Zeichenkette in Code-Einheiten einer implementierungsdefinierten 32-Bit-Kodierung (typischerweise UTF-32) einschließlich des Nullterminators ist. Jedes char32_t-Element im Array wird initialisiert, als ob mbrtoc32 in einer implementierungsdefinierten Locale ausgeführt worden wäre.
(bis C23)
3) UTF-16-Zeichenkettenliteral: Der Typ des Literals ist char16_t[N], wobei N die Größe der Zeichenkette in UTF-16-Code-Einheiten einschließlich des Nullterminators ist. Jedes char16_t-Element im Array wird aus dem nächsten Mehrbytezeichen in s-char-sequence unter Verwendung der UTF-16-Kodierung initialisiert.
4) UTF-32-Zeichenkettenliteral: Der Typ des Literals ist char32_t[N], wobei N die Größe der Zeichenkette in UTF-32-Code-Einheiten einschließlich des Nullterminators ist. Jedes char32_t-Element im Array wird aus dem nächsten Mehrbytezeichen in s-char-sequence unter Verwendung der UTF-32-Kodierung initialisiert.
(seit C23)
5) Wide-Zeichenkettenliteral: Der Typ des Literals ist wchar_t[N], wobei N die Größe der Zeichenkette in Code-Einheiten der breiten Ausführungskodierung einschließlich des Nullterminators ist. Jedes wchar_t-Element im Array wird initialisiert, als ob mbstowcs in einer implementierungsdefinierten Locale ausgeführt worden wäre.

[bearbeiten] Erklärung

Zuerst, in Übersetzungsphase 6 (nach Makroerweiterung), werden benachbarte Zeichenkettenliterale (d. h. nur durch Leerzeichen getrennte Zeichenkettenliterale) verkettet.

Nur zwei schmale oder zwei breite Zeichenkettenliterale dürfen verkettet werden.

(bis C99)

Wenn ein Literal unpräfixiert ist, hat das resultierende Zeichenkettenliteral die Breite/Kodierung, die durch das präfixierte Literal angegeben wird.

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

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

(seit C11)
(bis C23)

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

(seit C23)

Zweitens, in Übersetzungsphase 7, wird jedem Zeichenkettenliteral ein abschließendes Nullzeichen hinzugefügt, und dann initialisiert jedes Literal ein unbenanntes Array mit statischer Speicherdauer und einer Länge, die gerade ausreicht, um den Inhalt des Zeichenkettenliterals plus eins für den Nullterminator aufzunehmen.

char* p = "\x12" "3"; // creates a static char[3] array holding {'\x12', '3', '\0'}
                      // sets p to point to the first element of the array

Zeichenkettenliterale sind nicht modifizierbar (und können tatsächlich in schreibgeschütztem Speicher wie .rodata platziert werden). Wenn ein Programm versucht, das durch ein Zeichenkettenliteral gebildete statische Array zu modifizieren, ist das Verhalten undefiniert.

char* p = "Hello";
p[1] = 'M'; // Undefined behavior
char a[] = "Hello";
a[1] = 'M'; // OK: a is not a string literal

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

"def" == 3+"abcdef"; // may be 1 or 0, implementation-defined

[bearbeiten] Hinweise

Ein Zeichenkettenliteral ist nicht notwendigerweise eine Zeichenkette; wenn ein Zeichenkettenliteral eingebettete Nullzeichen enthält, repräsentiert es ein Array, das mehr als eine Zeichenkette enthält.

char* p = "abc\0def"; // strlen(p) == 3, but the array has size 8

Wenn einer Hexadezimal-Escape-Sequenz eine gültige Hexadezimalziffer folgt, würde dies als ungültige Escape-Sequenz zu einem Kompilierungsfehler führen, aber die Zeichenkettenverkettung kann als Workaround verwendet werden.

//char* p = "\xfff"; // error: hex escape sequence out of range
char* p = "\xff""f"; // okay, the literal is char[3] holding {'\xff', 'f', '\0'}

Zeichenkettenliterale können verwendet werden, um Arrays zu initialisieren. Wenn die Größe des Arrays um eins kleiner ist als die Größe des Zeichenkettenliterals, wird der Nullterminator ignoriert.

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

Die Kodierung von Zeichenkettenliteralen (1) und breiten Zeichenkettenliteralen (5) ist implementierungsabhängig. Zum Beispiel wählt gcc diese mit den Kommandozeilenoptionen -fexec-charset und -fwide-exec-charset.

Obwohl die Verkettung von gemischten breiten Zeichenkettenliteralen in C11 erlaubt ist, lehnen fast alle Compiler eine solche Verkettung ab (die einzige bekannte Ausnahme ist SDCC), und die Erfahrung mit ihrer Verwendung ist unbekannt. Daher wird die Erlaubnis zur Verkettung von gemischten breiten Zeichenkettenliteralen in C23 entfernt.

[bearbeiten] 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 }

[bearbeiten] Referenzen

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

[bearbeiten] Siehe auch

C++ Dokumentation für Zeichenkettenliteral