Spec-Zone.ru › C

Включение бинарных ресурсов (с 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)
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 - Последовательность одного или более h-charов, где появление любого из следующего приводит к неопределённому поведению:
  • символ '
  • символ "
  • символ \
  • последовательность символов //
  • последовательность символов /*
h-char - Любой член набора символов источника с исключением новой строки и >
q-char-sequence - Последовательность одного или более q-charов, где появление любого из следующего приводит к неопределённому поведению:
  • символ '
  • символ \
  • последовательность символов //
  • последовательность символов /*
q-char - Любой член набора символов источника с исключением новой строки и "
pp-tokens - Последовательность одного или более токенов препроцессора
string-literal - Строковая литерал
h-pp-tokens - Последовательность одного или более токенов препроцессора за исключением >
embed-parameter-sequence - Последовательность одного или более pp-parameter ов. Отличие от attribute-list в том, что эта последовательность не разделена запятыми.
pp-parameter - attribute-token (см.: атрибуты), но состоящий из токенов препроцессора вместо самих токенов.
pp-balanced-token-sequence - balanced-token-sequence (см.: атрибуты), но состоящий из токенов препроцессора вместо самих токенов

Объяснение

1) Поиск ресурса, идентифицируемого по h-char-sequence, производится по определённому реализацией способу.
2) Поиск ресурса, идентифицируемого по q-char-sequence, выполняется по определённому реализацией способу. Для (1,2), реализации обычно используют механизм, похожий, но отличный от механизма, используемого для включения файлов исходного кода. Конструкции __has_embed(__FILE__ ... в одном из примеров стандарта предполагают, что в случае (2), по крайней мере, проверяется каталог, где находится текущий файл.
3) Токены препроцессора после embed в директиве обрабатываются так же, как и обычный текст (т.е. каждое идентификатор, в настоящее время определённое как имя макроса, заменяется его списком токенов-заменителей). Результирующая директива после всех замен должна соответствовать одной из двух предыдущих форм. Способ объединения последовательности токенов препроцессора между парой токенов < и > или парой символов " в один токен имени заголовка — определяется реализацией.
4) Ресурс, идентифицируемый по h-char-sequence или q-char-sequence, ищется так, как если бы эта последовательность токенов препроцессора была pp-tokens в синтаксисе (3), за исключением того, что дальнейшее расширение макросов не выполняется. Если такая директива не удовлетворяет синтаксическим требованиям директивы #embed, программа является некорректной. Выражение __has__embed оценивается как __STDC_EMBED_FOUND__ при успешном поиске ресурса, непустом ресурсе и поддержке всех параметров, как __STDC_EMBED_EMPTY__ при пустом ресурсе и поддержке всех параметров и как __STDC_EMBED_NOT_FOUND__ при неудачном поиске или при неподдержке одного из передаваемых параметров реализацией.
5) Эта форма рассматривается только в случае, если синтаксис (4) не совпадает, в этом случае токены препроцессора обрабатываются так же, как и обычный текст.

В случае, если ресурс не найден или один из параметров не поддерживается реализацией, программа является некорректной.

__has_embed может быть раскрыто в выражении #if и #elif. Оно обрабатывается как определённый макрос #ifdef, #ifndef, #elifdef, #elifndef и defined, но не может быть использовано в других местах.

Ресурс имеет ширину ресурса реализации, которая представляет собой определённую реализацией размер ресурса в битах. Его ширина ресурса равна ширине ресурса реализации, если не изменена параметром limit. Если ширина ресурса равна 0, ресурс считается пустым. Ширина элемента встраивания равна CHAR_BIT, если не изменена параметром, определённым реализацией. Ширина ресурса должна быть кратна ширине элемента встраивания.

Расширение директивы #embed — это последовательность токенов, образованная из списка целых константных выражений, описанных ниже. Группа токенов для каждого целого константного выражения в списке отделяется в последовательности токенов от группы токенов предыдущего целого константного выражения в списке запятой. Последовательность не начинается и не заканчивается запятой. Если список целых константных выражений пуст, последовательность токенов пуста. Директива заменяется своим расширением и, при наличии определённых параметров встраивания, дополнительными или заменяющими последовательностями токенов.

Значения целочисленных константных выражений в расширенной последовательности определяются реализацией с помощью сопоставления данных ресурса. Каждое целочисленное константное выражение имеет значение в диапазоне [0, 2ширина элемента вставки). Если:

  1. Список целочисленных константных выражений используется для инициализации массива типа, совместимого с unsigned char, или совместимого с char если char не может хранить отрицательные значения, и
  2. Ширина элемента вставки равна CHAR_BIT,

то содержимое инициализированных элементов массива такое же, как если бы двоичные данные ресурса были fread в массив во время трансляции.

Реализации рекомендуется учитывать порядок битов и байтов во время трансляции, а также во время выполнения, чтобы точнее представить двоичные данные ресурса из директивы. Это максимизирует вероятность того, что, если ресурс, на который ссылаются во время трансляции с помощью директивы #embed, является тем же, к которому обращаются во время выполнения, данные, например, fread или аналогичные в непрерывном хранилище, будут полностью совпадать с битовым уровнем массиву символьного типа, инициализированному из расширенного содержимого директивы #embed.

Параметры

Стандарт определяет параметры limit, prefix, suffix и if_empty. Любой другой параметр, который появляется в директиве, должен быть определён реализацией, иначе программа некорректна. Определяемые реализацией параметры вставки могут изменить семантику директивы.

limit

limit( константное выражение ) (1)
__limit__( константное выражение ) (2)

Параметр вставки limit может появиться не более одного раза в последовательности параметров вставки. Он должен иметь аргумент, который должен быть целочисленным (предпроцессорным) константным выражением, значение которого равно неотрицательному числу и не содержит токен defined. Ширина ресурса устанавливается как минимум в произведение значения целочисленного константного выражения и ширины элемента вставки, а также ширины ресурса реализации.

suffix

suffix( последовательность токенов сбалансированных предпроцессором (необязательно) ) (1)
__suffix__( последовательность токенов сбалансированных предпроцессором (необязательно) ) (2)

Параметр вставки suffix может появиться не более одного раза в последовательности параметров вставки. Он должен иметь (возможно, пустую) секцию аргументов предпроцессора. Если ресурс не пустой, содержимое секции аргументов размещается непосредственно после расширения директивы. В противном случае, оно не оказывает влияния.

prefix

prefix( последовательность токенов сбалансированных предпроцессором (необязательно) ) (1)
__prefix__( последовательность токенов сбалансированных предпроцессором (необязательно) ) (2)

Параметр вставки prefix может появиться не более одного раза в последовательности параметров вставки. Он должен иметь (возможно, пустую) секцию аргументов предпроцессора. Если ресурс не пустой, содержимое секции аргументов размещается непосредственно перед расширением директивы. В противном случае, оно не оказывает влияния.

if_empty

if_empty( последовательность токенов сбалансированных предпроцессором (необязательно) ) (1)
__if_empty__( последовательность токенов сбалансированных предпроцессором (необязательно) ) (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' // 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:2023):
    • 6.4.7 Имена заголовков (стр. 69)
    • 6.10.1 Условное включение (стр. 165-169)
    • 6.10.2 Включение двоичных ресурсов (стр. 170-177)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/c/preprocessor/embed

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API