Binary resource inclusion (since C23)
#embed はビルド時に(バイナリ)リソースを含めるためのプリプロセッサディレクティブであり、リソースは翻訳環境からアクセス可能なデータソースとして定義されます。
目次 |
構文
#embed <
h-char-sequence
>
embed-parameter-sequence
(オプション)
new-line
|
(1) | ||||||||
#embed "
q-char-sequence
"
embed-parameter-sequence
(オプション)
new-line
|
(2) | ||||||||
#embed
pp-tokens
new-line
|
(3) | ||||||||
__has_embed
(
"
q-char-sequence
"
embed-parameter-sequence
(オプション)
)
__has_embed
(
<
h-char-sequence
>
embed-parameter-sequence
(オプション)
)
|
(4) | ||||||||
__has_embed
(
string-literal
pp-balanced-token-sequence
(オプション)
)
__has_embed
(
<
h-pp-tokens
>
pp-balanced-token-sequence
(オプション)
)
|
(5) | ||||||||
| new-line | - | 改行文字 |
| h-char-sequence | - |
1つ以上の
h-char
のシーケンス。以下のいずれかが出現すると未定義動作を引き起こす:
|
| h-char | - | 改行と > を除く ソース文字セット の任意のメンバー |
| q-char-sequence | - |
1つ以上の
q-char
のシーケンス。以下のいずれかが出現すると未定義動作を引き起こす:
|
| q-char | - | 改行と " を除く ソース文字セット の任意のメンバー |
| pp-tokens | - | 1つ以上の 前処理トークン のシーケンス |
| string-literal | - | 文字列リテラル string literal |
| h-pp-tokens | - | > を除く1つ以上の 前処理トークン のシーケンス |
| embed-parameter-sequence | - | 1つ以上の pp-parameter のシーケンス。 attribute-list とは異なり、このシーケンスはカンマで区切られていないことに注意。 |
| pp-parameter | - | トークンの代わりに前処理トークンで構成される attribute-token (参照: attributes ) |
| pp-balanced-token-sequence | - | トークンの代わりに前処理トークンで構成される balanced-token-sequence (参照: attributes ) |
説明
embed
に続く前処理トークンは、通常のテキストと同様に処理されます(つまり、マクロ名として現在定義されている各識別子は、その置換リストの前処理トークンで置き換えられます)。すべての置換後に得られるディレクティブは、前述の2つの形式のいずれかに一致しなければなりません。
<
と
>
の前処理トークンペア、または
"
文字のペアの間にある前処理トークンのシーケンスが単一のヘッダー名前処理トークンに結合される方法は、実装定義です。
リソースが見つからない場合、またはパラメータの1つが実装によってサポートされていない場合、プログラムは不適格(ill-formed)となります。
__has_embed は #if および #elif の式内で展開できます。 #ifdef 、 #ifndef 、 #elifdef 、 #elifndef および defined によって定義済みマクロとして扱われますが、他の場所では使用できません。
リソースには
実装リソース幅
があり、これは実装定義のビット単位でのロケート済みリソースのサイズです。その
リソース幅
は、
limit
パラメータによって変更されない限り、実装リソース幅となります。リソース幅が0の場合、リソースは空と見なされます。
埋め込み要素幅
は、実装定義のパラメータによって変更されない限り、
CHAR_BIT
と等しくなります。リソース幅は埋め込み要素幅で割り切れなければなりません。
#embed
ディレクティブの展開は、以下に説明する整数
定数式
のリストから形成されるトークン列です。リスト内の各整数定数式に対するトークングループは、前の整数定数式に対するトークングループからコンマで区切られます。このトークン列はコンマで始まることもコンマで終わることもありません。整数定数式のリストが空の場合、トークン列も空になります。このディレクティブはその展開で置き換えられ、特定のembedパラメータの存在に応じて、追加または置換のトークン列が付加されます。
拡張されたシーケンス内の整数定数式の値は、リソースのデータに対する実装定義のマッピングによって決定されます。各整数定数式の値は
[
0
,
2
embed element width
)
の範囲内にあります。もし:
- 整数定数式のリストは、 unsigned char と互換性のある型の配列を初期化するために使用され、または char が負の値を保持できない場合に char と互換性のある型の配列を初期化するために使用され、かつ
- embed要素の幅が CHAR_BIT と等しいこと、
その後、配列の初期化された要素の内容は、リソースのバイナリデータが翻訳時に配列に fread されたかのようになります。
実装は、翻訳時のビット順序とバイト順序、および実行時のビット順序とバイト順序を考慮して、ディレクティブからのリソースのバイナリデータをより適切に表現することが推奨されます。これにより、翻訳時に #embed ディレクティブを通じて参照されたリソースが実行時の手段(例えば fread など)でアクセスされた同じリソースである場合、連続ストレージに読み込まれたデータが、 #embed ディレクティブの展開内容から初期化された文字型配列とビット単位で完全に一致する可能性が最大化されます。
パラメータ
標準では
limit
、
prefix
、
suffix
および
if_empty
のパラメータを定義しています。ディレクティブ内に現れるその他のパラメータは実装定義でなければならず、そうでない場合プログラムは不適格となります。実装定義の埋め込みパラメータはディレクティブのセマンティクスを変更する可能性があります。
リミット
limit(
constant-expression
)
|
(1) | ||||||||
__limit__(
constant-expression
)
|
(2) | ||||||||
`タグ内の`limit`、`__limit__`、`constant-expression`はC++固有の用語であり、翻訳対象外です。数値の`(1)`と`(2)`も翻訳対象外です。そのため、元のHTML構造と内容は完全に保持されています。
limit
埋め込みパラメータは、埋め込みパラメータシーケンス内に最大1回のみ出現できます。引数を持つ必要があり、その引数は非負の数値に評価され、トークン
defined
を含まない整数(プリプロセッサ)
定数式
でなければなりません。リソース幅は、整数定数式に埋め込み要素の幅を乗算した値と、実装のリソース幅の最小値に設定されます。
サフィックス
suffix(
pp-balanced-token-sequence
(オプション)
)
|
(1) | ||||||||
__suffix__(
pp-balanced-token-sequence
(オプション)
)
|
(2) | ||||||||
suffix
埋め込みパラメータは、埋め込みパラメータシーケンス内に最大1回のみ出現できます。これは(空でも可能な)プリプロセッサ引数節を持たなければなりません。リソースが空でない場合、パラメータ節の内容はディレクティブの展開直後に配置されます。それ以外の場合、効果はありません。
プレフィックス
prefix(
pp-balanced-token-sequence
(オプション)
)
|
(1) | ||||||||
__prefix__(
pp-balanced-token-sequence
(オプション)
)
|
(2) | ||||||||
prefix
埋め込みパラメータは、埋め込みパラメータシーケンス内に最大1回のみ出現できます。このパラメータは(空でも可能な)プリプロセッサ引数節を持たなければなりません。リソースが空でない場合、パラメータ節の内容はディレクティブの展開直前に配置されます。それ以外の場合、このパラメータは効果を持ちません。
if_empty
if_empty(
pp-balanced-token-sequence
(オプション)
)
|
(1) | ||||||||
__if_empty__(
pp-balanced-token-sequence
(オプション)
)
|
(2) | ||||||||
if_empty
埋め込みパラメータは、埋め込みパラメータシーケンス内に最大1回のみ出現できます。これは(空でも可能な)プリプロセッサ引数節を持たなければなりません。リソースが空の場合、パラメータ節の内容がディレクティブを置き換えます。それ以外の場合、効果はありません。
例
#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); }
出力例:
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
参考文献
- C23規格 (ISO/IEC 9899:2024):
-
- 6.4.7 ヘッダー名 (p: 69)
-
- 6.10.1 条件付きインクルード (p: 165-169)
-
- 6.10.2 バイナリリソースインクルード (p: 170-177)
関連項目
|
C++ documentation
for
リソースインクルージョン
(C++26以降)
|