バイナリリソースのインクルード (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 | - | 文字列リテラル。 |
| 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つの形式のいずれかに一致する必要があります。< と > のプリプロセッサートークンペアの間、または " 文字のペアの間に配置されるプリプロセッサートークンのシーケンスが、単一のヘッダー名プリプロセッサートークンに結合される方法は、実装定義です。__has__embed 式は、リソースの検索が成功し、リソースが空でなく、すべてのパラメータがサポートされている場合は __STDC_EMBED_FOUND__ に、リソースが空で、すべてのパラメータがサポートされている場合は __STDC_EMBED_EMPTY__ に、検索に失敗したか、渡されたパラメータのいずれかが実装でサポートされていない場合は __STDC_EMBED_NOT_FOUND__ に評価されます。リソースが見つからない場合、またはパラメータのいずれかが実装でサポートされていない場合、プログラムは不正な形式となります。
__has_embed は、 #if および #elif の式で展開できます。これは、 #ifdef、 #ifndef、 #elifdef、 #elifndef、および defined によって定義済みマクロとして扱われますが、それ以外の場所では使用できません。
リソースには *実装リソース幅* があり、これは検索されたリソースのビット単位での実装定義サイズです。その *リソース幅* は、limit パラメータによって変更されない限り、実装リソース幅です。リソース幅が 0 の場合、リソースは空とみなされます。*埋め込み要素幅* は、実装定義パラメータによって変更されない限り、CHAR_BIT と等しくなります。リソース幅は、埋め込み要素幅で割り切れる必要があります。
#embed ディレクティブの展開は、以下で説明する整数 定数式 のリストから形成されるトークンシーケンスです。リスト内の各整数定数式のトークンのグループは、リスト内の前の整数定数式のトークンのグループからカンマによってトークンシーケンスで区切られます。シーケンスはカンマで始まったり終わったりしません。整数定数式のリストが空の場合、トークンシーケンスは空です。ディレクティブは、その展開に置き換えられ、特定の埋め込みパラメータの存在により、追加または置換のトークンシーケンスが生成されます。
展開されたシーケンス内の整数定数式の値は、リソースのデータの実装定義マッピングによって決定されます。各整数定数式の値は、[0, 2embed element width) の範囲にあります。もし
- 整数定数式のリストが、unsigned char 型、または char が負の値を保持できない場合は char 型と互換性のある配列を初期化するために使用され、そして
- 埋め込み要素幅が CHAR_BIT に等しい場合、
初期化された配列要素の内容は、翻訳時にリソースのバイナリデータが配列に fread されたかのように扱われます。
実装は、翻訳時のビット順序およびバイト順序、ならびに実行時のビット順序およびバイト順序を考慮して、ディレクティブからリソースのバイナリデータをより適切に表現することが推奨されます。これにより、翻訳時に #embed ディレクティブを介して参照されたリソースが、実行時にアクセスされるリソースと同じである場合、fread などで連続ストレージに読み込まれたデータが、#embed ディレクティブの展開された内容から初期化された文字型配列とビット単位で等しく比較される可能性が最大になります。
[編集] パラメータ
標準では、limit、prefix、suffix、および if_empty パラメータが定義されています。ディレクティブに現れる他のパラメータは、実装定義であるか、プログラムが不正な形式であるかのいずれかです。実装定義の埋め込みパラメータは、ディレクティブの意味を変える可能性があります。
[編集] limit
limit( constant-expression ) |
(1) | ||||||||
__limit__( constant-expression ) |
(2) | ||||||||
limit 埋め込みパラメータは、埋め込みパラメータシーケンスに最大1回出現できます。引数が必要であり、非負の数値を評価し、defined トークンを含まない整数(プリプロセッサ)定数式である必要があります。リソース幅は、整数定数式に埋め込み要素幅を掛けた値と、実装リソース幅の最小値に設定されます。
[編集] suffix
suffix( pp-balanced-token-sequence (オプション) ) |
(1) | ||||||||
__suffix__( pp-balanced-token-sequence (オプション) ) |
(2) | ||||||||
suffix 埋め込みパラメータは、埋め込みパラメータシーケンスに最大1回出現できます。(空の場合もある)プリプロセッサ引数句が必要です。リソースが空でない場合、パラメータ句の内容はディレクティブの展開の直後に配置されます。それ以外の場合は、効果はありません。
[編集] prefix
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++ ドキュメント (リソースインクルード (C++26以降))
|