Binary resource inclusion (since C23)
#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) | ||||||||
| 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:
|
| 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:
|
| 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
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.
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:
- 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
- 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)
|