String literals
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
.
|
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.
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) |
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
|