Binary resource inclusion (since C23)
#embed est une directive de préprocesseur permettant d'inclure des ressources (binaires) dans la compilation, où une ressource est définie comme une source de données accessible depuis l'environnement de traduction.
         Table des matières | 
       
Syntaxe
         
          
           #embed <
          
         
         
          h-char-sequence
         
         
          
           >
          
         
         
          embed-parameter-sequence
         
         
         
          (optionnel)
         
         
          new-line
         
         | 
        (1) | ||||||||
         
          
           #embed "
          
         
         
          q-char-sequence
         
         
          
           "
          
         
         
          embed-parameter-sequence
         
         
         
          (optionnel)
         
         
          new-line
         
         | 
        (2) | ||||||||
         
          
           #embed
          
         
         
          pp-tokens
         
         
          new-line
         
         | 
        (3) | ||||||||
         
          
           __has_embed
          
         
         
          
           (
          
         
         
          
           "
          
         
         
          q-char-sequence
         
         
          
           "
          
         
         
          embed-parameter-sequence
         
         
         
          (optionnel)
         
         
          
           )
          
         
         
          
           __has_embed
          
         
         
          
           (
          
         
         
          
           <
          
         
         
          h-char-sequence
         
         
          
           >
          
         
         
          embed-parameter-sequence
         
         
         
          (optionnel)
         
         
          
           )
          
         
         | 
        (4) | ||||||||
         
          
           __has_embed
          
         
         
          
           (
          
         
         
          string-literal
         
         
          pp-balanced-token-sequence
         
         
         
          (optionnel)
         
         
          
           )
          
         
         
          
           __has_embed
          
         
         
          
           (
          
         
         
          
           <
          
         
         
          h-pp-tokens
         
         
          
           >
          
         
         
          pp-balanced-token-sequence
         
         
         
          (optionnel)
         
         
          
           )
          
         
         | 
        (5) | ||||||||
| new-line | - | Le caractère de nouvelle ligne | 
| h-char-sequence | - | 
         Une séquence d'un ou plusieurs
         
          h-char
         
         s, où l'apparition de l'un des éléments suivants provoque un comportement indéfini :
         
  | 
       
| h-char | - | Tout membre du jeu de caractères source sauf le caractère de nouvelle ligne et > | 
| q-char-sequence | - | 
         Une séquence d'un ou plusieurs
         
          q-char
         
         s, où l'apparition de l'un des éléments suivants provoque un comportement indéfini :
         
  | 
       
| q-char | - | Tout membre du jeu de caractères source sauf le caractère de nouvelle ligne et " | 
| pp-tokens | - | Une séquence d'un ou plusieurs jetons de prétraitement | 
| string-literal | - | Un littéral de chaîne | 
| h-pp-tokens | - | Une séquence d'un ou plusieurs jetons de prétraitement sauf > | 
| embed-parameter-sequence | - | Une séquence d'un ou plusieurs pp-parameter s. Notez que contrairement à une attribute-list , cette séquence n'est pas séparée par des virgules. | 
| pp-parameter | - | Un attribute-token (voir : attributs ) mais composé de jetons de prétraitement au lieu de jetons. | 
| pp-balanced-token-sequence | - | Une balanced-token-sequence (voir : attributs ) mais composée de jetons de prétraitement au lieu de jetons | 
Explication
        
         embed
        
       
       dans la directive sont traités comme dans le texte normal (c'est-à-dire que chaque identifiant actuellement défini comme nom de macro est remplacé par sa liste de remplacement de jetons de prétraitement). La directive résultant après tous les remplacements doit correspondre à l'une des deux formes précédentes. La méthode par laquelle une séquence de jetons de prétraitement entre
       
        
         
          <
         
        
       
       et
       
        
         
          >
         
        
       
       ou une paire de caractères
       
        
         
          "
         
        
       
       est combinée en un seul jeton de prétraitement de nom d'en-tête est définie par l'implémentation.
      Dans le cas où la ressource n'est pas trouvée ou si l'un des paramètres n'est pas pris en charge par l'implémentation, le programme est mal formé.
__has_embed peut être développé dans l'expression de #if et #elif . Il est traité comme une macro définie par #ifdef , #ifndef , #elifdef , #elifndef et defined mais ne peut pas être utilisé ailleurs.
       Une ressource possède une
       
        largeur de ressource d'implémentation
       
       qui est la taille en bits définie par l'implémentation de la ressource localisée. Sa
       
        largeur de ressource
       
       est la largeur de ressource d'implémentation sauf si modifiée par un paramètre
       
        limit
       
       . Si la largeur de ressource est 0, la ressource est considérée comme vide. La
       
        largeur d'élément d'incorporation
       
       est égale à
       
        
         
          
           CHAR_BIT
          
         
        
       
       sauf si modifiée par un paramètre défini par l'implémentation. La largeur de ressource doit être divisible par la largeur d'élément d'incorporation.
      
       L'expansion d'une directive
       
        #embed
       
       est une séquence de jetons formée à partir de la liste d'
       
        expressions constantes
       
       entières décrite ci-dessous. Le groupe de jetons pour chaque expression constante entière dans la liste est séparé dans la séquence de jetons du groupe de jetons pour l'expression constante entière précédente dans la liste par une virgule. La séquence ne commence ni ne se termine par une virgule. Si la liste d'expressions constantes entières est vide, la séquence de jetons est vide. La directive est remplacée par son expansion et, avec la présence de certains paramètres d'embed, des séquences de jetons supplémentaires ou de remplacement.
      
       Les valeurs des expressions constantes entières dans la séquence développée sont déterminées par un mappage défini par l'implémentation des données de la ressource. La valeur de chaque expression constante entière se situe dans l'intervalle
       
        
         [
        
        0
        
         ,
        
        2
        
         embed element width
        
        
         )
        
       
       . Si :
      
- La liste d'expressions constantes entières est utilisée pour initialiser un tableau d'un type compatible avec unsigned char , ou compatible avec char si char ne peut pas contenir de valeurs négatives, et
 - La largeur de l'élément embed est égale à CHAR_BIT ,
 
alors le contenu des éléments initialisés du tableau est comme si les données binaires de la ressource étaient fread dans le tableau au moment de la traduction.
Les implémentations sont encouragées à prendre en compte l'ordre des bits et des octets au moment de la traduction ainsi que l'ordre des bits et des octets au moment de l'exécution pour représenter plus adéquatement les données binaires de la ressource à partir de la directive. Cela maximise la probabilité que, si la ressource référencée au moment de la traduction via la directive #embed est la même que celle accédée par des moyens au moment de l'exécution, les données qui sont par exemple lues par fread ou similaire dans un stockage contigu seront comparées bit à bit égales à un tableau de type caractère initialisé à partir du contenu développé de la directive #embed .
Paramètres
       La norme définit les paramètres
       
        limit
       
       ,
       
        prefix
       
       ,
       
        suffix
       
       et
       
        if_empty
       
       . Tout autre paramètre apparaissant dans la directive doit être défini par l'implémentation, sinon le programme est mal formé. Les paramètres d'incorporation définis par l'implémentation peuvent modifier la sémantique de la directive.
      
limite
         
          
           limit(
          
         
         
          expression-constante
         
         
          
           )
          
         
         | 
        (1) | ||||||||
         
          
           __limit__(
          
         
         
          expression-constante
         
         
          
           )
          
         
         | 
        (2) | ||||||||
       Le paramètre d'intégration
       
        limit
       
       ne peut apparaître qu'une seule fois dans la séquence de paramètres d'intégration. Il doit avoir un argument, qui doit être une expression constante (préprocesseur)
       
        constante
       
       qui évalue un nombre non négatif et ne contient pas le jeton
       
        defined
       
       . La largeur de ressource est définie au minimum de l'expression constante entière multipliée par la largeur de l'élément d'intégration et la largeur de ressource d'implémentation.
      
suffixe
         
          
           suffix(
          
         
         
          séquence-de-jetons-pp-équilibrée
         
         
         
          (optionnel)
         
         
          
           )
          
         
         | 
        (1) | ||||||||
         
          
           __suffix__(
          
         
         
          séquence-de-jetons-pp-équilibrée
         
         
         
          (optionnel)
         
         
          
           )
          
         
         | 
        (2) | ||||||||
       Le paramètre d'intégration
       
        suffix
       
       ne peut apparaître qu'une seule fois au maximum dans la séquence de paramètres d'intégration. Il doit avoir une clause d'argument de préprocesseur (éventuellement vide). Si la ressource n'est pas vide, le contenu de la clause de paramètre est placé immédiatement après l'expansion de la directive. Sinon, il n'a aucun effet.
      
préfixe
         
          
           prefix(
          
         
         
          séquence-de-jetons-équilibrés-pp
         
         
         
          (optionnel)
         
         
          
           )
          
         
         | 
        (1) | ||||||||
         
          
           __prefix__(
          
         
         
          séquence-de-jetons-équilibrés-pp
         
         
         
          (optionnel)
         
         
          
           )
          
         
         | 
        (2) | ||||||||
       Le paramètre d'intégration
       
        prefix
       
       ne peut apparaître qu'une seule fois dans la séquence de paramètres d'intégration. Il doit avoir une clause d'argument de préprocesseur (éventuellement vide). Si la ressource n'est pas vide, le contenu de la clause de paramètre est placé immédiatement avant l'expansion de la directive. Sinon, il n'a aucun effet.
      
if_empty
         
          
           if_empty(
          
         
         
          séquence-de-jetons-équilibrés-pp
         
         
         
          (optionnel)
         
         
          
           )
          
         
         | 
        (1) | ||||||||
         
          
           __if_empty__(
          
         
         
          séquence-de-jetons-équilibrés-pp
         
         
         
          (optionnel)
         
         
          
           )
          
         
         | 
        (2) | ||||||||
       Le paramètre d'intégration
       
        if_empty
       
       ne peut apparaître qu'une seule fois dans la séquence de paramètres d'intégration. Il doit avoir une clause d'argument de préprocesseur (éventuellement vide). Si la ressource est vide, le contenu de la clause de paramètre remplace la directive. Sinon, il n'a aucun effet.
      
Exemple
#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' // terminateur nul }; 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); }
Sortie possible :
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
Références
- Norme C23 (ISO/CEI 9899:2024) :
 
- 
         
- 6.4.7 Noms d'en-tête (p: 69)
 
 
- 
         
- 6.10.1 Inclusion conditionnelle (p: 165-169)
 
 
- 
         
- 6.10.2 Inclusion de ressources binaires (p: 170-177)
 
 
Voir aussi
| 
          
          
           
            Documentation C++
           
          
          pour
          
           
            Inclusion de ressources
            
             (depuis C++26)
            
           
          
          
         |