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 | - |
Последовательность одного или более
h-char
s, где появление любого из следующих вызывает неопределённое поведение:
|
| h-char | - | Любой элемент исходного набора символов кроме новой строки и > |
| q-char-sequence | - |
Последовательность одного или более
q-char
s, где появление любого из следующих вызывает неопределённое поведение:
|
| q-char | - | Любой элемент исходного набора символов кроме новой строки и " |
| pp-tokens | - | Последовательность одного или более токенов препроцессора |
| string-literal | - | Строковый литерал |
| h-pp-tokens | - | Последовательность одного или более токенов препроцессора кроме > |
| embed-parameter-sequence | - | Последовательность одного или более pp-parameter s. Обратите внимание, что в отличие от attribute-list , эта последовательность не разделяется запятыми. |
| pp-parameter | - | attribute-token (см.: attributes ), но состоящий из токенов препроцессора вместо токенов. |
| pp-balanced-token-sequence | - | balanced-token-sequence (см.: attributes ), но состоящий из токенов препроцессора вместо токенов |
Объяснение
embed
в директиве обрабатываются так же, как в обычном тексте (т.е. каждое имя идентификатора, определённое в настоящее время как имя макроса, заменяется его списком замены препроцессинг-токенов). Директива, полученная после всех замен, должна соответствовать одной из двух предыдущих форм. Способ, которым последовательность препроцессинг-токенов между
<
и
>
парой препроцессинг-токенов или парой
"
символов объединяется в единый токен имени заголовка, определяется реализацией.
В случае, если ресурс не найден или один из параметров не поддерживается реализацией, программа является некорректно сформированной.
__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
. Любые другие параметры, присутствующие в директиве, должны быть определены реализацией, иначе программа является некорректной. Определяемые реализацией параметры embed могут изменять семантику директивы.
предел
limit(
constant-expression
)
|
(1) | ||||||||
__limit__(
constant-expression
)
|
(2) | ||||||||
`, `
`, `
Параметр встраивания
limit
может встречаться не более одного раза в последовательности параметров встраивания. Он должен иметь аргумент, который должен быть целочисленным (препроцессорным)
константным выражением
, вычисляющимся в неотрицательное число и не содержащим токен
defined
. Ширина ресурса устанавливается как минимум из целочисленного константного выражения, умноженного на ширину элемента встраивания, и ширины ресурса реализации.
суффикс
suffix(
pp-balanced-token-sequence
(необязательно)
)
|
(1) | ||||||||
__suffix__(
pp-balanced-token-sequence
(необязательно)
)
|
(2) | ||||||||
Параметр встраивания
suffix
может встречаться не более одного раза в последовательности параметров встраивания. Он должен иметь (возможно, пустой) аргумент препроцессора. Если ресурс не пуст, содержимое параметра помещается непосредственно после раскрытия директивы. В противном случае он не оказывает никакого эффекта.
префикс
prefix(
pp-balanced-token-sequence
(необязательно)
)
|
(1) | ||||||||
__prefix__(
pp-balanced-token-sequence
(необязательно)
)
|
(2) | ||||||||
Параметр встраивания
prefix
может встречаться не более одного раза в последовательности параметров встраивания. Он должен иметь (возможно, пустой) аргумент препроцессора. Если ресурс не пуст, содержимое параметра помещается непосредственно перед раскрытием директивы. В противном случае он не оказывает никакого эффекта.
if_empty
if_empty(
pp-balanced-token-sequence
(необязательно)
)
|
(1) | ||||||||
__if_empty__(
pp-balanced-token-sequence
(необязательно)
)
|
(2) | ||||||||
Параметр встраивания
if_empty
может встречаться не более одного раза в последовательности параметров встраивания. Он должен иметь (возможно, пустой) аргумент препроцессора. Если ресурс пуст, содержимое параметра заменяет директиву. В противном случае он не оказывает никакого эффекта.
Пример
#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' // нулевой терминатор }; 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 Имена заголовков (стр: 69)
-
- 6.10.1 Условное включение (стр: 165-169)
-
- 6.10.2 Включение бинарных ресурсов (стр: 170-177)
Смотрите также
|
C++ documentation
для
Включение ресурсов
(начиная с C++26)
|