Namespaces
Variants

Binary resource inclusion (since C23)

From cppreference.net

#embed ist eine Präprozessor-Direktive zum Einbinden (binärer) Ressourcen in den Build, wobei eine Ressource als eine Datenquelle definiert ist, die aus der Übersetzungsumgebung zugänglich ist.

Inhaltsverzeichnis

Syntax

#embed < h-char-sequence > embed-parameter-sequence  (optional) new-line (1)
#embed " q-char-sequence " embed-parameter-sequence  (optional) new-line (2)
#embed pp-tokens new-line (3)
__has_embed ( " q-char-sequence " embed-parameter-sequence  (optional) )
__has_embed ( < h-char-sequence > embed-parameter-sequence  (optional) )
(4)
__has_embed ( string-literal pp-balanced-token-sequence  (optional) )
__has_embed ( < h-pp-tokens > pp-balanced-token-sequence  (optional) )
(5)
1) Sucht nach einer Ressource, die eindeutig durch h-char-sequence identifiziert wird, und ersetzt die Direktive durch eine durch Kommas getrennte Liste von Ganzzahlen, die den Daten der Ressource entsprechen.
2) Such nach einer Ressource, identifiziert durch q-char-sequence , und ersetzt die Direktive durch eine Liste von Ganzzahlen, die den Daten der Ressource entsprechen. Es kann auf (1) zurückgreifen.
3) Wenn weder (1) noch (2) zutrifft, werden pp-tokens einer Makroersetzung unterzogen. Die Anweisung wird nach der Ersetzung erneut versucht, mit (1) oder (2) abgeglichen zu werden.
4) Prüft, ob eine Ressource für die Einbettung verfügbar ist, ob sie leer ist oder nicht und ob die übergebenen Parameter von der Implementierung unterstützt werden.
5) Wenn (4) nicht übereinstimmt, werden h-pp-tokens und pp-balanced-token-sequence einer Makroersetzung unterzogen. Die Anweisung nach der Ersetzung wird erneut versucht, mit (4) abgeglichen zu werden.
new-line - Das Zeilenumbruchzeichen
h-char-sequence - Eine Sequenz von einem oder mehreren h-char s, wobei das Auftreten eines der folgenden Elemente undefiniertes Verhalten verursacht:
  • das Zeichen '
  • das Zeichen "
  • das Zeichen \
  • die Zeichensequenz //
  • die Zeichensequenz /*
h-char - Jedes Element des Quellzeichensatzes außer Zeilenumbruch und >
q-char-sequence - Eine Sequenz von einem oder mehreren q-char s, wobei das Auftreten eines der folgenden Elemente undefiniertes Verhalten verursacht:
  • das Zeichen '
  • das Zeichen \
  • die Zeichensequenz //
  • die Zeichensequenz /*
q-char - Jedes Element des Quellzeichensatzes außer Zeilenumbruch und "
pp-tokens - Eine Sequenz von einem oder mehreren Präprozessor-Tokens
string-literal - Ein Zeichenkettenliteral
h-pp-tokens - Eine Sequenz von einem oder mehreren Präprozessor-Tokens außer >
embed-parameter-sequence - Eine Sequenz von einem oder mehreren pp-parameter s. Beachten Sie, dass diese Sequenz im Gegensatz zu einer attribute-list nicht durch Kommas getrennt ist.
pp-parameter - Ein attribute-token (siehe: attributes ), bestehend aus Präprozessor-Tokens anstelle von Tokens.
pp-balanced-token-sequence - Eine balanced-token-sequence (siehe: attributes ), bestehend aus Präprozessor-Tokens anstelle von Tokens

Erklärung

1) Sucht nach der durch h-char-sequence identifizierten Ressource auf implementierungsdefinierte Weise.
2) Such nach der Ressource, die durch q-char-sequence identifiziert wird, auf implementierungsdefinierte Weise. Für (1,2) verwenden die Implementierungen typischerweise einen Mechanismus, der ähnlich, aber verschieden ist von den implementierungsdefinierten Suchpfaden, die für source file inclusion verwendet werden. Das Konstrukt __has_embed ( __FILE__ ... erscheint in einem der Beispiele im Standard, was nahelegt, dass zumindest im Fall (2) erwartet wird, dass das Verzeichnis, in dem die aktuelle Datei sich befindet, durchsucht wird.
3) Die Präprozessortoken nach embed in der Direktive werden genauso verarbeitet wie in normalem Text (d.h., jeder als Makroname definierte Bezeichner wird durch seine Ersetzungsliste von Präprozessortoken ersetzt). Die nach allen Ersetzungen resultierende Direktive muss einer der beiden vorherigen Formen entsprechen. Die Methode, durch die eine Sequenz von Präprozessortoken zwischen < und > Präprozessortoken-Paaren oder einem Paar von " Zeichen zu einem einzelnen Header-Namen-Präprozessortoken kombiniert wird, ist implementierungsdefiniert.
4) Die durch h-char-sequence oder q-char-sequence identifizierte Ressource wird so durchsucht, als ob diese Präprozessor-Token-Sequenz die pp-tokens in Syntax (3) wäre, mit der Ausnahme, dass keine weitere Makroexpansion durchgeführt wird. Falls eine solche Direktive die syntaktischen Anforderungen einer #embed -Direktive nicht erfüllen würde, ist das Programm fehlerhaft. Der __has_embed -Ausdruck ergibt __STDC_EMBED_FOUND__ , wenn die Suche nach der Ressource erfolgreich ist, die Ressource nicht leer ist und alle Parameter unterstützt werden, __STDC_EMBED_EMPTY__ , wenn die Ressource leer ist und alle Parameter unterstützt werden, und __STDC_EMBED_NOT_FOUND__ , wenn die Suche fehlschlägt oder einer der übergebenen Parameter von der Implementierung nicht unterstützt wird.
5) Diese Form wird nur berücksichtigt, wenn die Syntax (4) nicht übereinstimmt, in welchem Fall die Präprozessor-Tokens genauso wie in normalem Text verarbeitet werden.

Falls die Ressource nicht gefunden wird oder einer der Parameter von der Implementierung nicht unterstützt wird, ist das Programm fehlerhaft.

__has_embed kann im Ausdruck von #if und #elif expandiert werden. Es wird von #ifdef , #ifndef , #elifdef , #elifndef und defined als definiertes Makro behandelt, kann jedoch nirgendwo anders verwendet werden.

Eine Ressource hat eine Implementierungsressourcenbreite , welche die implementierungsdefinierte Größe in Bits der lokalisierten Ressource ist. Ihre Ressourcenbreite ist die Implementierungsressourcenbreite, sofern nicht durch einen limit -Parameter modifiziert. Wenn die Ressourcenbreite 0 ist, wird die Ressource als leer betrachtet. Die Einbettungselementbreite ist gleich CHAR_BIT , sofern nicht durch einen implementierungsdefinierten Parameter modifiziert. Die Ressourcenbreite muss durch die Einbettungselementbreite teilbar sein.

Die Erweiterung einer #embed Direktive ist eine Token-Sequenz, die aus der nachfolgend beschriebenen Liste von ganzzahligen konstanten Ausdrücken gebildet wird. Die Gruppe von Tokens für jeden ganzzahligen konstanten Ausdruck in der Liste wird in der Token-Sequenz durch ein Komma von der Token-Gruppe des vorherigen ganzzahligen konstanten Ausdrucks in der Liste getrennt. Die Sequenz beginnt und endet nicht mit einem Komma. Wenn die Liste der ganzzahligen konstanten Ausdrücke leer ist, ist die Token-Sequenz leer. Die Direktive wird durch ihre Erweiterung ersetzt und, bei Vorhandensein bestimmter Embed-Parameter, durch zusätzliche oder ersetzende Token-Sequenzen.

Die Werte der ganzzahligen konstanten Ausdrücke in der erweiterten Sequenz werden durch eine implementierungsdefinierte Abbildung der Ressourcendaten bestimmt. Der Wert jedes ganzzahligen konstanten Ausdrucks liegt im Bereich [ 0 , 2 embed element width ) . Wenn:

  1. Die Liste der ganzzahligen konstanten Ausdrücke wird verwendet, um ein Array eines mit unsigned char kompatiblen Typs zu initialisieren, oder kompatibel mit char falls char keine negativen Werte halten kann, und
  2. Die Breite des Embed-Elements entspricht CHAR_BIT ,

dann sind die Inhalte der initialisierten Elemente des Arrays so, als ob die binären Daten der Ressource zur Übersetzungszeit in das Array fread würden.

Implementierungen sind angehalten, Übersetzungszeit-Bit- und Byte-Reihenfolgen sowie Ausführungszeit-Bit- und Byte-Reihenfolgen zu berücksichtigen, um die binären Daten der Ressource aus der Direktive angemessener darzustellen. Dies maximiert die Wahrscheinlichkeit, dass – falls die Ressource, die zur Übersetzungszeit über die #embed -Direktive referenziert wird, dieselbe ist, die zur Laufzeit über Mechanismen wie fread oder ähnliche Zugriffsmethoden in zusammenhängenden Speicher eingelesen wird – die Daten bitgenau mit einem Array von Zeichentyp übereinstimmen, das aus den expandierten Inhalten einer #embed -Direktive initialisiert wurde.

Parameter

Die Norm definiert die Parameter limit , prefix , suffix und if_empty . Jeder andere Parameter, der in der Direktive erscheint, muss implementierungsdefiniert sein, oder das Programm ist fehlerhaft. Implementierungsdefinierte Embed-Parameter können die Semantik der Direktive ändern.

Limit

limit( constant-expression ) (1)
__limit__( constant-expression ) (2)

Der limit Embed-Parameter darf höchstens einmal in der Embed-Parameter-Sequenz vorkommen. Er muss ein Argument haben, das ein ganzzahliger (Präprozessor) constant expression sein muss, der zu einer nicht-negativen Zahl ausgewertet wird und nicht das Token defined enthält. Die Ressourcenbreite wird auf das Minimum des ganzzahligen konstanten Ausdrucks multipliziert mit der Embed-Elementbreite und der Implementierungsressourcenbreite gesetzt.

Suffix

suffix( pp-balanced-token-sequence  (optional) ) (1)
__suffix__( pp-balanced-token-sequence  (optional) ) (2)

Der suffix Embed-Parameter darf höchstens einmal in der Embed-Parameter-Sequenz vorkommen. Er muss eine (möglicherweise leere) Präprozessor-Argumentklausel haben. Wenn die Ressource nicht leer ist, werden die Inhalte der Parameterklausel unmittelbar nach der Expansion der Direktive platziert. Andernfalls hat er keine Wirkung.

Präfix

prefix( pp-balanced-token-sequence  (optional) ) (1)
__prefix__( pp-balanced-token-sequence  (optional) ) (2)

Der prefix -Einbettungsparameter darf höchstens einmal in der Einbettungsparameterfolge erscheinen. Er muss eine (möglicherweise leere) Präprozessor-Argumentklausel haben. Wenn die Ressource nicht leer ist, werden die Inhalte der Parameterklausel unmittelbar vor der Expansion der Direktive platziert. Andernfalls hat er keine Wirkung.

if_empty

if_empty( pp-balanced-token-sequence  (optional) ) (1)
__if_empty__( pp-balanced-token-sequence  (optional) ) (2)

Der if_empty Embed-Parameter darf höchstens einmal in der Embed-Parameter-Sequenz erscheinen. Er muss eine (möglicherweise leere) Präprozessor-Argumentklausel haben. Wenn die Ressource leer ist, ersetzen die Inhalte der Parameterklausel die Direktive. Andernfalls hat er keine Wirkung.

Beispiel

#include <stdint.h>
#include <stdio.h>
const uint8_t image_data[] =
{
#embed "image.png"
};
const char message[] =
{
#embed "message.txt" if_empty('M', 'i', 's', 's', 'i', 'n', 'g', '\n')
,'\0' // Null-Terminator
};
void dump(const uint8_t arr[], size_t size)
{
    for (size_t i = 0; i != size; ++i)
        printf("%02X%c", arr[i], (i + 1) % 16 ? ' ' : '\n');
    puts("");
}
int main()
{
    puts("image_data[]:");
    dump(image_data, sizeof image_data);
    puts("message[]:");
    dump((const uint8_t*)message, sizeof message);
}

Mögliche Ausgabe:

image_data[]:
89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52
00 00 00 01 00 00 00 01 01 03 00 00 00 25 DB 56
...
message[]:
4D 69 73 73 69 6E 67 0A 00

Referenzen

  • C23-Standard (ISO/IEC 9899:2024):
  • 6.4.7 Header-Namen (S: 69)
  • 6.10.1 Bedingte Einbindung (S: 165-169)
  • 6.10.2 Binäre Ressourcen-Einbindung (S: 170-177)

Siehe auch

C++ Dokumentation für Ressourcen-Einbindung (seit C++26)