GNU-Erweiterung: Raw-Strings
Zeichenketten mit vielen Sonderzeichen, etwa reguläre Ausdrücke oder XML, erfordern in Standard-C aufwändiges Escapen. Escape-Sequenzen wie \", \\ oder \n geben bestimmten Zeichen eine spezielle Bedeutung. Jedes dieser Zeichen muss im Literal verdoppelt oder maskiert werden. Der Code wird dadurch schwer lesbar und fehleranfällig.
GCC und einige andere Compiler erweitern C um Raw-String-Literale, die keine Escape-Verarbeitung durchführen.
(Quelle: https://gcc.gnu.org/onlinedocs/gcc/Raw-String-Literals.html)
Diese Erweiterung stammt aus C{plus} und ist dort seit C++11 Teil des Standards. GCC übernimmt die Syntax für C, sobald mit -std=gnu99 oder einem anderen GNU-Mode kompiliert wird. Die Portabilität bleibt aber eingeschränkt, weil Raw-Strings nicht im C23-Standard enthalten sind und Compiler wie MSVC diese Schreibweise in C nicht verstehen.
Jede Zeichenfolge im Raw-String wird unverändert übernommen und Backslashes, Anführungszeichen oder andere Zeichen werden nicht interpretiert.
Die Syntax beginnt mit R", gefolgt von einem optionalen Delimiter, dem Inhalt und dem schließenden Delimiter plus ". Ohne Delimiter lautet sie R"(Inhalt)".
Ein Beispiel ohne eigenen Delimiter:
#include <stdio.h>
int main() {
const char *normal_pattern = "\\d{3}-\\d{3}-\\d{4}";
const char *raw_pattern = R"(\d{3}-\d{3}-\d{4})";
const char *normal_xml = "<tag attr=\"value\">Text</tag>";
const char *raw_xml = R"(<tag attr="value">Text</tag>)";
puts(normal_pattern);
puts(raw_pattern);
puts(normal_xml);
puts(raw_xml);
}
Ein eigener Delimiter ist hier nicht nötig, weil der Inhalt keine Sequenz enthält, die R"(…)" unbeabsichtigt schließen könnte.
Ein praktischer Fall für einen eigenen Delimiter entsteht bei JSON. Darin finden sich häufig gemischte Anführungszeichen und Backslashes. Taucht dabei eine Sequenz wie )" im Text auf, endet ein Raw-String ohne Delimiter zu früh. Ein eigener Delimiter verhindert das:
#include <stdio.h>
int main() {
// Ohne Raw-String: viele Escapes, schlecht lesbar
const char *json_normal =
"{ \"text\": \"A)\\\" Beispiel\", \"value\": 42 }";
// Mit Raw-String und Delimiter json
const char *json_raw =
R"json({ "text": "A)\" Beispiel", "value": 42 })json";
puts(json_normal);
puts(json_raw);
}
Der JSON-Inhalt enthält die Folge )". Würde man R"(…)" nutzen, würde die Sequenz )" mitten im Text das Literal beenden. Durch den Delimiter json endet das Literal erst bei )json". Damit bleibt der JSON-Text unverändert.
Raw-Strings sind ein eigener Literaltyp und folgen den gleichen Regeln wie normale String-Literale. Das heißt: Mehrere Raw-Strings können direkt hintereinander stehen und werden vom Compiler zu einem einzigen String zusammengefügt. Auch das Mischen mit normalen Literalen funktioniert, weil die Konkatenation rein auf Token-Ebene passiert.
const char *json_raw =
"{"
R"json("text": "A)\" Beispiel")json"
","
R"json("value": 42)json"
"}";
Für portable Projekte bietet sich als Alternative nur das Aneinanderreihen von String-Literalen an, oder das Auslagern langer Inhalte in externe Dateien.