Binary resource inclusion (since C23)
#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) | ||||||||
| 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:
|
| 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:
|
| 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
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.
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:
- 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
- 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)
|