Namespaces
Variants

Binary resource inclusion (since C23)

From cppreference.net

#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)
1) 一意に識別されるリソースを h-char-sequence で検索し、そのディレクティブをリソースのデータに対応する整数のカンマ区切りリストで置き換えます。
2) q-char-sequence によって識別されるリソースを検索し、そのリソースのデータに対応する整数のリストでディレクティブを置き換えます。 (1) にフォールバックする可能性があります。
3) もし (1) (2) のどちらにもマッチしない場合、 pp-tokens はマクロ置換を受けます。置換後のディレクティブは再度 (1) または (2) とのマッチングが試行されます。
4) リソースが埋め込み可能かどうか、空であるかどうか、および渡されたパラメータが実装でサポートされているかどうかをチェックします。
5) もし (4) が一致しない場合、 h-pp-tokens pp-balanced-token-sequence はマクロ置換を受けます。置換後のディレクティブは (4) との一致が再度試行されます。
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

説明

1) 実装定義の方法で h-char-sequence によって識別されるリソースを検索します。
2) q-char-sequence で識別されるリソースを実装定義の方法で検索します。 (1,2) の場合、実装は通常、 ソースファイルインクルード に使用される実装定義の検索パスと類似しているが異なるメカニズムを使用します。標準の例の1つに __has_embed ( __FILE__ ... という構文が現れており、少なくとも (2) の場合、現在のファイルが存在するディレクトリが検索対象になると予想されることを示唆しています。
3) ディレクティブ内の embed に続く前処理トークンは、通常のテキストと同様に処理されます(つまり、マクロ名として現在定義されている各識別子は、その置換リストの前処理トークンで置き換えられます)。すべての置換後に得られるディレクティブは、前述の2つの形式のいずれかに一致しなければなりません。 < > の前処理トークンペア、または " 文字のペアの間にある前処理トークンのシーケンスが単一のヘッダー名前処理トークンに結合される方法は、実装定義です。
4) h-char-sequence または q-char-sequence によって識別されるリソースは、その前処理トークン列が構文 (3) pp-tokens であるかのように検索されますが、それ以上のマクロ展開は行われません。このようなディレクティブが #embed ディレクティブの構文要件を満たさない場合、プログラムは不適格となります。 __has_embed 式は、リソースの検索が成功し、リソースが空でなく、すべてのパラメータがサポートされている場合 __STDC_EMBED_FOUND__ に、リソースが空でかつすべてのパラメータがサポートされている場合 __STDC_EMBED_EMPTY__ に、検索が失敗した場合または渡されたパラメータの1つが実装によってサポートされていない場合 __STDC_EMBED_NOT_FOUND__ に評価されます。
5) この形式は、構文 (4) が一致しない場合にのみ考慮され、その場合、前処理トークンは通常のテキストと同様に処理されます。

リソースが見つからない場合、またはパラメータの1つが実装によってサポートされていない場合、プログラムは不適格(ill-formed)となります。

__has_embed #if および #elif の式内で展開できます。 #ifdef #ifndef #elifdef #elifndef および defined によって定義済みマクロとして扱われますが、他の場所では使用できません。

リソースには 実装リソース幅 があり、これは実装定義のビット単位でのロケート済みリソースのサイズです。その リソース幅 は、 limit パラメータによって変更されない限り、実装リソース幅となります。リソース幅が0の場合、リソースは空と見なされます。 埋め込み要素幅 は、実装定義のパラメータによって変更されない限り、 CHAR_BIT と等しくなります。リソース幅は埋め込み要素幅で割り切れなければなりません。

#embed ディレクティブの展開は、以下に説明する整数 定数式 のリストから形成されるトークン列です。リスト内の各整数定数式に対するトークングループは、前の整数定数式に対するトークングループからコンマで区切られます。このトークン列はコンマで始まることもコンマで終わることもありません。整数定数式のリストが空の場合、トークン列も空になります。このディレクティブはその展開で置き換えられ、特定のembedパラメータの存在に応じて、追加または置換のトークン列が付加されます。

拡張されたシーケンス内の整数定数式の値は、リソースのデータに対する実装定義のマッピングによって決定されます。各整数定数式の値は [ 0 , 2 embed element width ) の範囲内にあります。もし:

  1. 整数定数式のリストは、 unsigned char と互換性のある型の配列を初期化するために使用され、または char が負の値を保持できない場合に char と互換性のある型の配列を初期化するために使用され、かつ
  2. embed要素の幅が CHAR_BIT と等しいこと、

その後、配列の初期化された要素の内容は、リソースのバイナリデータが翻訳時に配列に fread されたかのようになります。

実装は、翻訳時のビット順序とバイト順序、および実行時のビット順序とバイト順序を考慮して、ディレクティブからのリソースのバイナリデータをより適切に表現することが推奨されます。これにより、翻訳時に #embed ディレクティブを通じて参照されたリソースが実行時の手段(例えば fread など)でアクセスされた同じリソースである場合、連続ストレージに読み込まれたデータが、 #embed ディレクティブの展開内容から初期化された文字型配列とビット単位で完全に一致する可能性が最大化されます。

パラメータ

標準では limit prefix suffix および if_empty のパラメータを定義しています。ディレクティブ内に現れるその他のパラメータは実装定義でなければならず、そうでない場合プログラムは不適格となります。実装定義の埋め込みパラメータはディレクティブのセマンティクスを変更する可能性があります。

リミット

limit( constant-expression ) (1)
__limit__( constant-expression ) (2)
**注記**: このHTMLコードでは、翻訳対象となるテキストがほとんど含まれていません。` `タグ内の`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以降)