Namespaces
Variants

Binary resource inclusion (since C23)

From cppreference.net

#embed es una directiva del preprocesador para incluir recursos (binarios) en la compilación, donde un recurso se define como una fuente de datos accesible desde el entorno de traducción.

Contenidos

Sintaxis

#embed < h-char-sequence > embed-parameter-sequence  (opcional) new-line (1)
#embed " q-char-sequence " embed-parameter-sequence  (opcional) new-line (2)
#embed pp-tokens new-line (3)
__has_embed ( " q-char-sequence " embed-parameter-sequence  (opcional) )
__has_embed ( < h-char-sequence > embed-parameter-sequence  (opcional) )
(4)
__has_embed ( string-literal pp-balanced-token-sequence  (opcional) )
__has_embed ( < h-pp-tokens > pp-balanced-token-sequence  (opcional) )
(5)
1) Busca un recurso identificado de forma única por h-char-sequence y reemplaza la directiva por una lista de enteros separados por comas correspondiente a los datos del recurso.
2) Busca un recurso identificado por q-char-sequence y reemplaza la directiva por una lista de enteros correspondientes a los datos del recurso. Puede recurrir a (1) .
3) Si ni (1) ni (2) coinciden, pp-tokens sufrirán reemplazo de macro. La directiva después del reemplazo se intentará hacer coincidir con (1) o (2) nuevamente.
4) Verifica si un recurso está disponible para incrustación, si está vacío o no y si los parámetros pasados son compatibles con la implementación.
5) Si (4) no coincide, h-pp-tokens y pp-balanced-token-sequence sufrirán reemplazo de macro. La directiva después del reemplazo se intentará hacer coincidir con (4) nuevamente.
new-line - El carácter de nueva línea
h-char-sequence - Una secuencia de uno o más h-char s, donde la aparición de cualquiera de los siguientes causa comportamiento indefinido:
  • el carácter '
  • el carácter "
  • el carácter \
  • la secuencia de caracteres //
  • la secuencia de caracteres /*
h-char - Cualquier miembro del juego de caracteres fuente excepto nueva línea y >
q-char-sequence - Una secuencia de uno o más q-char s, donde la aparición de cualquiera de los siguientes causa comportamiento indefinido:
  • el carácter '
  • el carácter \
  • la secuencia de caracteres //
  • la secuencia de caracteres /*
q-char - Cualquier miembro del juego de caracteres fuente excepto nueva línea y "
pp-tokens - Una secuencia de uno o más tokens de preprocesamiento
string-literal - Un literal de cadena
h-pp-tokens - Una secuencia de uno o más tokens de preprocesamiento excepto >
embed-parameter-sequence - Una secuencia de uno o más pp-parameter s. Nótese que a diferencia de una attribute-list , esta secuencia no está separada por comas.
pp-parameter - Un attribute-token (ver: attributes ) pero compuesto por tokens de preprocesamiento en lugar de tokens.
pp-balanced-token-sequence - Una balanced-token-sequence (ver: attributes ) pero compuesta por tokens de preprocesamiento en lugar de tokens

Explicación

1) Busca el recurso identificado por h-char-sequence de manera definida por la implementación.
2) Busca el recurso identificado por q-char-sequence de manera definida por la implementación. Para (1,2) , las implementaciones típicamente utilizan un mecanismo similar, pero distinto, a las rutas de búsqueda definidas por la implementación usadas para source file inclusion . El constructo __has_embed ( __FILE__ ... aparece en uno de los ejemplos del estándar, sugiriendo, en el caso (2) al menos, que se espera que se busque en el directorio donde reside el archivo actual.
3) Los tokens de preprocesamiento después de embed en la directiva se procesan igual que en el texto normal (es decir, cada identificador actualmente definido como nombre de macro se reemplaza por su lista de reemplazo de tokens de preprocesamiento). La directiva resultante después de todos los reemplazos deberá coincidir con una de las dos formas anteriores. El método mediante el cual una secuencia de tokens de preprocesamiento entre < y > par de tokens de preprocesamiento o un par de caracteres " se combina en un solo token de preprocesamiento de nombre de cabecera está definido por la implementación.
4) El recurso identificado por h-char-sequence o q-char-sequence se busca como si esa secuencia de tokens de preprocesamiento fuera los pp-tokens en la sintaxis (3) , excepto que no se realiza ninguna expansión de macros adicional. Si dicha directiva no cumpliera los requisitos sintácticos de una directiva #embed , el programa está mal formado. La __has_embed expresión se evalúa como __STDC_EMBED_FOUND__ si la búsqueda del recurso tiene éxito, el recurso no está vacío y todos los parámetros son compatibles, como __STDC_EMBED_EMPTY__ si el recurso está vacío y todos los parámetros son compatibles, y como __STDC_EMBED_NOT_FOUND__ si la búsqueda falla o uno de los parámetros pasados no es compatible con la implementación.
5) Esta forma se considera solo si la sintaxis (4) no coincide, en cuyo caso los tokens de preprocesamiento se procesan igual que en el texto normal.

En caso de que el recurso no se encuentre o uno de los parámetros no sea compatible con la implementación, el programa está mal formado.

__has_embed puede expandirse en la expresión de #if y #elif . Es tratado como una macro definida por #ifdef , #ifndef , #elifdef , #elifndef y defined pero no puede utilizarse en ningún otro lugar.

Un recurso tiene un ancho de recurso de implementación que es el tamaño definido por la implementación en bits del recurso localizado. Su ancho de recurso es el ancho de recurso de implementación a menos que sea modificado por un parámetro limit . Si el ancho de recurso es 0, el recurso se considera vacío. El ancho de elemento de incrustación es igual a CHAR_BIT a menos que sea modificado por un parámetro definido por la implementación. El ancho de recurso debe ser divisible por el ancho de elemento de incrustación.

La expansión de una directiva #embed es una secuencia de tokens formada a partir de la lista de expresiones constantes enteras descritas a continuación. El grupo de tokens para cada expresión constante entera en la lista está separado en la secuencia de tokens del grupo de tokens para la expresión constante entera anterior en la lista por una coma. La secuencia no comienza ni termina con una coma. Si la lista de expresiones constantes enteras está vacía, la secuencia de tokens está vacía. La directiva es reemplazada por su expansión y, con la presencia de ciertos parámetros de embed, secuencias de tokens adicionales o de reemplazo.

Los valores de las expresiones constantes enteras en la secuencia expandida se determinan mediante un mapeo definido por la implementación de los datos del recurso. El valor de cada expresión constante entera está en el rango [ 0 , 2 embed element width ) . Si:

  1. La lista de expresiones constantes enteras se utiliza para inicializar un array de un tipo compatible con unsigned char , o compatible con char si char no puede contener valores negativos, y
  2. El ancho del elemento embed es igual a CHAR_BIT ,

entonces los contenidos de los elementos inicializados del array son como-si los datos binarios del recurso se fread en el array en tiempo de traducción.

Se recomienda a las implementaciones que consideren los órdenes de bits y bytes en tiempo de traducción, así como los órdenes de bits y bytes en tiempo de ejecución, para representar de manera más apropiada los datos binarios del recurso desde la directiva. Esto maximiza la probabilidad de que, si el recurso referenciado en tiempo de traducción a través de la directiva #embed es el mismo al que se accede por medios en tiempo de ejecución, los datos que son, por ejemplo, fread o similares en almacenamiento contiguo se compararán bit a bit iguales a un arreglo de tipo carácter inicializado a partir del contenido expandido de una directiva #embed .

Parámetros

El estándar define los parámetros limit , prefix , suffix y if_empty . Cualquier otro parámetro que aparezca en la directiva debe estar definido por la implementación, o el programa está mal formado. Los parámetros de incrustación definidos por la implementación pueden cambiar la semántica de la directiva.

límite

limit( expresión-constante ) (1)
__limit__( expresión-constante ) (2)

El limit parámetro embed puede aparecer como máximo una vez en la secuencia de parámetros embed. Debe tener un argumento, que debe ser una expresión constante (preprocesador) constant expression que evalúe a un número no negativo y no contenga el token defined . El ancho del recurso se establece al mínimo del resultado de multiplicar la expresión constante entera por el ancho del elemento embed y el ancho del recurso de implementación.

sufijo

suffix( secuencia-de-tokens-equilibrada-pp  (opcional) ) (1)
__suffix__( secuencia-de-tokens-equilibrada-pp  (opcional) ) (2)

El parámetro de incrustación suffix puede aparecer como máximo una vez en la secuencia de parámetros de incrustación. Debe tener una cláusula de argumento de preprocesador (posiblemente vacía). Si el recurso no está vacío, el contenido de la cláusula de parámetro se coloca inmediatamente después de la expansión de la directiva. De lo contrario, no tiene efecto.

prefijo

prefix( secuencia-de-tokens-equilibrada-pp  (opcional) ) (1)
__prefix__( secuencia-de-tokens-equilibrada-pp  (opcional) ) (2)

El prefix parámetro embed puede aparecer como máximo una vez en la secuencia de parámetros embed. Debe tener una cláusula de argumento de preprocesador (posiblemente vacía). Si el recurso no está vacío, el contenido de la cláusula de parámetro se coloca inmediatamente antes de la expansión de la directiva. De lo contrario, no tiene efecto.

if_empty

if_empty( secuencia-de-tokens-equilibrada-pp  (opcional) ) (1)
__if_empty__( secuencia-de-tokens-equilibrada-pp  (opcional) ) (2)

El parámetro de incrustación if_empty puede aparecer como máximo una vez en la secuencia de parámetros de incrustación. Debe tener una cláusula de argumento de preprocesador (posiblemente vacía). Si el recurso está vacío, el contenido de la cláusula del parámetro reemplaza la directiva. De lo contrario, no tiene efecto.

Ejemplo

#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' // terminador nulo
};
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);
}

Salida posible:

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

Referencias

  • Estándar C23 (ISO/IEC 9899:2024):
  • 6.4.7 Nombres de cabecera (p: 69)
  • 6.10.1 Inclusión condicional (p: 165-169)
  • 6.10.2 Inclusión de recursos binarios (p: 170-177)

Véase también

Documentación de C++ para Inclusión de recursos (desde C++26)