1. Changelog
1.1. Revision 3 - June 12th, 2026
-
Slightly adjust the Intent section of the paper to be more clear.
-
Move wording for resource-offset and resource-count jointly into [cpp.embed.gen] rather than having it in the [cpp.embed.param.offset] section.
-
Clean up extraneous examples and tighten up the
s/variable names of thestatic_assert examples.offset
1.2. Revision 2 - June 5th, 2025
-
Design was expanded upon in Revision 1 and further explicated in this version to prevent people from being confused about what is being proposed here and what the specification was asking for. It was not recorded in the previous changelog: it is being recorded here.
-
Revision 2 does not add or change any of the wording in a way that matters; it just fixes clerical errors, typos, and aligns dates.
-
One such typo: fixes "It shall provide" to "It provides", as the "shall" is spurious in C++ wording since it does not provide anything.
-
§ 3 Design elaborates that this is meant to be that
applies beforeoffset is applied, as what is implemented inlimit andclang :: offset today.gnu :: offset -
Some discussion during an SG22 meeting about restricting the order of embed parameters. This isn’t present in any implementation or in the C wording, and it’s an awful experience overall: rejected this design to proceed forward.
1.3. Revision 1 - February 14th, 2025
-
Minor typo and wording cleanup.
1.4. Revision 0 - December 13th, 2024
-
Initial release.
2. Introduction and Motivation
The goal is to add the extremely-popular and already-implemented and parameters as standard parameters. That is the only motivation of this proposal; to standardize existing practice.
Originally, users asked to add this parameter, but only after C23 standardized. Given the late stage that users have asked -- waiting until the very end -- it has to be added separately. This proposal aims to standardize what users have asked for, and what Clang and GCC have implemented.
3. Design
The design of is straightforward:
-
discardsoffset items, up to the full size of the resource;some - preprocessor - constant - value -
nothing happens if
evaluates tosome - preprocessor - constant - value ;0 -
if
is greater than or equal to the size of the resource, the resource is considered empty;offset -
does not shrink the file to a given size beforelimit ;offset is applied to the original file size (called the "implementation-resource-count" in the wording).offset
These are the only tenets of the design, and match the practice for existing implementations and . It is also how the original author envisioned this when it was first PR’d to Clang, and the original tests (plus new ones) still pass in the LLVM/clang and gnu/gcc repositories.
There was some discussion during the June 4th, 2025 about the order of parameters. This turned into a significant enough change that it is a separate paper. No additional discussion or changes are proposed for this paper: it is exactly a standardization of existing practice and what was approved in Austria.
4. Wording
This wording is relative to C++'s latest working draft.
4.1. Intent
The intent of the wording is to provide a preprocessing directive that:
-
allows an
parameter skipping over a number of elements before beginning to write out elements to the comma-delimited list;offset -
and, applies to the actual size of the resource (i.e., before any applied
parameter).limit
4.2. Feature Test Macro
The feature test macro should be increased from to , where . is determined by the Editors.
4.3. Proposed Language Wording
4.3.1. Add to the control-line production in §15.1 Preamble [cpp.pre] a new grammar production for offset
embed-standard-parameter:
limit ( pp-balanced-token-seq )
- offset ( pp-balanced-token-seq )
prefix ( pp-balanced-token-seqopt )
suffix ( pp-balanced-token-seqopt )
if_empty ( pp-balanced-token-seqopt )
4.3.2. Modify and add paragraphs in §15.4.1 General [cpp.embed.gen]
15.4.1 General [cpp.embed.gen]...
...
A resource is a source of data accessible from the translation environment. A resource has an implementation-resource-width, which is the implementation-defined size in bits of the resource. If the implementation-resource-width is not an integral multiple of
, the program is ill-formed. Let implementation-resource-count be implementation-resource-width divided byCHAR_BIT . Every resource has a resource-offset, which isCHAR_BIT
the value as computed from the optionally-provided
embed-parameter ([cpp.embed.param.offset]), if present;offset otherwise, 0.
Every resource also has a resource-count, which is
- if the
embed-parameter ([cpp.embed.param.limit]) is present, where the value computed from thelimit embed-parameter is limit-valuelimit the value as computed from the optionally-provided;embed-parameter ([cpp.embed.param.limit]), if presentlimit otherwise,
the implementation-resource-count.A resource is empty if the resource-count is zero.
...
..
The integer literals in the comma-separated list correspond to resource-count consecutive calls toFirst, resource-offset calls to([cstdio.syn]) from the resource, as a binary file.std :: fgetc from the resource as a binary file have their result discarded and ignored. Next, resource-count consecutive calls tostd :: fgetc produce the elements of the comma-separated list of integer literals, in order. If any of the resource-count calls tostd :: fgetc returnsstd :: fgetc , the program is ill-formed.EOF If any call toreturnsstd :: fgetc , the program is ill-formed.EOF
4.3.3. Add a new sub-clause §15.4.2.✨ under Resource Inclusion for Embed parameters for the new offset parameter [cpp.embed.param.offset]
15.4.2.✨parameter [cpp.embed.param.offset]offset An embed-parameter of the form
denotes the number of elements to be skipped from the resource. It shall appear at most once in the embed-parameter-seq.offset ( pp - balanced - token - seq ) The pp-balanced-token-seq is evaluated as a constant-expression using the rules as described in conditional inclusion ([cpp.cond]), but without being processed as in normal text an additional time.
The constant-expression shall be an integral constant expression whose value is greater than or equal to zero.
[Example:
constexpr const unsigned char arr [] = { // a hypothetical resource capable of expanding to // four or more elements #embed <sdk/jump.wav> }; constexpr const unsigned char offset_arr [] = { // the same hypothetical resource capable of expanding // to four or more elements #embed <sdk/jump.wav> offset(2) }; constexpr const unsigned char offset_limit_arr [] = { // the same hypothetical resource capable of expanding // to four or more elements #embed <sdk/jump.wav> offset(1) limit(1) }; static_assert ( arr [ 2 ] == offset_arr [ 0 ]); static_assert ( arr [ 3 ] == offset_arr [ 1 ]); static_assert ( arr [ 1 ] == offset_limit_arr [ 0 ]); – end example]
4.4. Remove the following text from [cpp.embed.param.limit], ❡3
The constant-expression shall be an integral constant expression whose value is greater than or equal to zero.
The resource-count ([cpp.embed.gen]) becomes implementation-resource-count, if the value of the constant-expression is greater than implementation-resource-count; otherwise, the value of the constant-expression.
4.5. Add a new example to the if_empty embed parameter [cpp.embed.param.if.empty] section
[Example: Given a resource
that has an implementation-resource-count of 1, the following directives:< single_byte > #embed <single_byte> offset(1) if_empty(42203) are replaced with:
42203 – end example]