Namespaces
Variants

Replacing text macros

From cppreference.net

Le préprocesseur prend en charge le remplacement de macros textuelles et le remplacement de macros textuelles de type fonction.

Table des matières

Syntaxe

#define identifiant liste-de-remplacement  (optionnel) (1)
#define identifiant  ( paramètres ) liste-de-remplacement (2)
#define identifiant  ( paramètres , ... ) liste-de-remplacement (3) (depuis C99)
#define identifiant  ( ... ) liste-de-remplacement (4) (depuis C99)
#undef identifiant (5)

Explication

#define directives

Les directives #define définissent l' identifiant comme une macro, c'est-à-dire qu'elles indiquent au compilateur de remplacer toutes les occurrences successives de l' identifiant par la liste-de-remplacement , qui peut éventuellement être traitée supplémentairement. Si l'identifiant est déjà défini comme un quelconque type de macro, le programme est mal formé sauf si les définitions sont identiques.

Macros de type objet

Les macros de type objet remplacent chaque occurrence d'un identifiant défini par une liste-de-remplacement . La version (1) de la directive #define se comporte exactement de cette manière.

Macros de type fonction

Les macros de type fonction remplacent chaque occurrence d'un identifiant défini par une liste-de-remplacement , en prenant également un certain nombre d'arguments qui remplacent ensuite les occurrences correspondantes des paramètres dans la liste-de-remplacement .

La syntaxe d'un appel de macro de type fonction est similaire à la syntaxe d'un appel de fonction : chaque occurrence du nom de la macro suivie d'un ( comme prochain jeton de préprocesseur introduit la séquence de jetons qui est remplacée par la liste de remplacement. La séquence se termine par le jeton ) correspondant, en sautant les paires correspondantes de parenthèses gauches et droites intermédiaires.

Le nombre d'arguments doit être le même que le nombre d'arguments dans la définition de la macro ( parameters ) ou le programme est mal formé. Si l'identifiant n'est pas en notation fonctionnelle, c'est-à-dire s'il n'a pas de parenthèses après lui-même, il n'est pas remplacé du tout.

La version (2) de la directive #define définit une macro simple de type fonction.

La version (3) de la directive #define définit une macro de type fonction avec un nombre variable d'arguments. Les arguments supplémentaires peuvent être accédés en utilisant l'identifiant __VA_ARGS__ , qui est ensuite remplacé par les arguments fournis avec l'identifiant à remplacer.

La version (4) de la directive #define définit une macro de type fonction avec un nombre variable d'arguments, mais sans arguments réguliers. Les arguments ne peuvent être accédés qu'avec l'identifiant __VA_ARGS__ , qui est ensuite remplacé par les arguments fournis avec l'identifiant à remplacer.

Pour les versions (3,4), replacement-list peut contenir la séquence de tokens __VA_OPT__ ( content ) , qui est remplacée par content si __VA_ARGS__ n'est pas vide, et se développe en rien sinon.

#define F(...) f(0 __VA_OPT__(,) __VA_ARGS__)
F(a, b, c) // replaced by f(0, a, b, c)
F()        // replaced by f(0)
#define G(X, ...) f(0, X __VA_OPT__(,) __VA_ARGS__)
G(a, b, c) // replaced by f(0, a, b, c)
G(a, )     // replaced by f(0, a)
G(a)       // replaced by f(0, a)
#define SDEF(sname, ...) S sname __VA_OPT__(= { __VA_ARGS__ })
SDEF(foo);       // replaced by S foo;
SDEF(bar, 1, 2); // replaced by S bar = { 1, 2 };
(depuis C23)


Remarque : si un argument d'une macro de type fonction contient des virgules qui ne sont pas protégées par des paires de parenthèses gauche et droite correspondantes (telles que macro ( array [ x = y, x + 1 ] ) ou atomic_store ( p, ( struct S ) { a, b } ) ; ), la virgule est interprétée comme un séparateur d'arguments de macro, provoquant une erreur de compilation due à une inadéquation du nombre d'arguments.

# et ## opérateurs

Dans les macros de type fonction, un opérateur # placé devant un identifiant dans la replacement-list soumet cet identifiant au remplacement des paramètres et encadre le résultat de guillemets, créant ainsi effectivement un littéral de chaîne. De plus, le préprocesseur ajoute des barres obliques inverses pour échapper les guillemets entourant les littéraux de chaîne intégrés, le cas échéant, et double les barres obliques inverses dans la chaîne si nécessaire. Tous les espaces blancs de début et de fin sont supprimés, et toute séquence d'espaces blancs au milieu du texte (mais pas à l'intérieur des littéraux de chaîne intégrés) est réduite à un seul espace. Cette opération est appelée « stringification ». Si le résultat de la stringification n'est pas un littéral de chaîne valide, le comportement est indéfini.

Lorsque # apparaît avant __VA_ARGS__ , l'intégralité de l'expansion de __VA_ARGS__ est placée entre guillemets :

#define showlist(...) puts(#__VA_ARGS__)
showlist();            // expands to puts("")
showlist(1, "x", int); // expands to puts("1, \"x\", int")
(depuis C99)

Un ## opérateur entre deux identifiants successifs dans la liste-de-remplacement effectue le remplacement des paramètres sur les deux identifiants puis concatène le résultat. Cette opération est appelée « concaténation » ou « collage de jetons ». Seuls les jetons qui forment ensemble un jeton valide peuvent être collés : des identifiants formant un identifiant plus long, des chiffres formant un nombre, ou les opérateurs + et = qui forment un += . Un commentaire ne peut pas être créé en collant / et * car les commentaires sont supprimés du texte avant que la substitution des macros ne soit considérée. Si le résultat de la concaténation n'est pas un jeton valide, le comportement est indéfini.

Note : Certains compilateurs proposent une extension qui permet à ## d'apparaître après une virgule et avant __VA_ARGS__ , auquel cas le ## ne fait rien lorsque __VA_ARGS__ n'est pas vide, mais supprime la virgule lorsque __VA_ARGS__ est vide : cela permet de définir des macros telles que fprintf ( stderr , format, ##__VA_ARGS__) .

L'ordre d'évaluation des opérateurs # et ## n'est pas spécifié.

#undef directive

La directive #undef supprime la définition de l' identifiant , c'est-à-dire qu'elle annule la définition précédente de l' identifiant par la directive #define . Si l'identifiant n'a pas de macro associée, la directive est ignorée.

Macros prédéfinies

Les noms de macro suivants sont prédéfinis dans toute unité de traduction :

__STDC__
s'étend à la constante entière 1 . Cette macro est destinée à indiquer une implémentation conforme
(constante de macro)
__STDC_VERSION__
(C95)
s'étend à une constante entière de type long dont la valeur augmente avec chaque version de la norme C :
  • 199409L (C95)
  • 199901L (C99)
  • 201112L (C11)
  • 201710L (C17)
  • 202311L (C23)
    (constante de macro)
__STDC_HOSTED__
(C99)
s'étend à la constante entière 1 si l'implémentation est hébergée (fonctionne sous un SE), 0 si autonome (fonctionne sans SE)
(constante de macro)
__FILE__
s'étend au nom du fichier courant, sous forme de littéral de chaîne de caractères, peut être modifié par la directive #line
(constante de macro)
__LINE__
s'étend au numéro de ligne du fichier source, une constante entière, peut être modifié par la directive #line
(constante de macro)
__DATE__
s'étend à la date de traduction, un littéral de chaîne de caractères de la forme « Mmm jj aaaa ». Le nom du mois est comme généré par asctime et le premier caractère de « jj » est un espace si le jour du mois est inférieur à 10
(constante de macro)
__TIME__
s'étend à l'heure de traduction, un littéral de chaîne de caractères de la forme « hh:mm:ss », comme dans l'heure générée par asctime ( )
(constante de macro)
__STDC_UTF_16__
(C23)
s'étend à 1 pour indiquer que char16_t utilise l'encodage UTF-16
(constante de macro)
__STDC_UTF_32__
(C23)
s'étend à 1 pour indiquer que char32_t utilise l'encodage UTF-32
(constante de macro)
__STDC_EMBED_NOT_FOUND__ __STDC_EMBED_FOUND__ __STDC_EMBED_EMPTY__
(C23)
s'étendent respectivement à 0 , 1 , et 2
(constante de macro)

Les noms de macro supplémentaires suivants peuvent être prédéfinis par une implémentation :

__STDC_ISO_10646__
(C99)
s'étend en une constante entière de la forme yyyymmL , si wchar_t utilise Unicode ; la date indique la dernière révision d'Unicode prise en charge
(constante macro)
__STDC_IEC_559__
(C99) (obsolète en C23)
s'étend à 1 si IEC 60559 est pris en charge
(constante macro)
__STDC_IEC_559_COMPLEX__
(C99) (déprécié en C23)
s'étend à 1 si l'arithmétique complexe IEC 60559 est prise en charge
(constante macro)
__STDC_UTF_16__
(C11)
s'étend à 1 si char16_t utilise l'encodage UTF-16
(constante macro)
__STDC_UTF_32__
(C11)
s'étend à 1 si char32_t utilise l'encodage UTF-32
(constante macro)
__STDC_MB_MIGHT_NEQ_WC__
(C99)
s'étend à 1 si 'x' == L 'x' peut être faux pour un membre du jeu de caractères de base, comme sur les systèmes basés sur EBCDIC qui utilisent Unicode pour wchar_t
(constante macro)
__STDC_ANALYZABLE__
(C11)
s'étend à 1 si l'analysabilité est prise en charge
(constante macro)
__STDC_LIB_EXT1__
(C11)
s'étend à une constante entière 201112L si les interfaces de vérification des limites sont prises en charge
(constante macro)
__STDC_NO_ATOMICS__
(C11)
s'étend à 1 si les types atomiques et la bibliothèque d'opérations atomiques ne sont pas pris en charge
(constante macro)
__STDC_NO_COMPLEX__
(C11)
s'étend à 1 si les types complexes et la bibliothèque mathématique complexe ne sont pas pris en charge
(constante macro)
__STDC_NO_THREADS__
(C11)
s'étend à 1 si la programmation multithread n'est pas prise en charge
(constante macro)
__STDC_NO_VLA__
(C11)
s'étend à 1 si les tableaux de longueur variable et les types modifiables de façon variable (jusqu'en C23) de durée de stockage automatique (depuis C23) ne sont pas pris en charge
(constante macro)
__STDC_IEC_60559_BFP__
(C23)
s'étend à 202311L si l'arithmétique binaire en virgule flottante IEC 60559 est prise en charge
(constante macro)
__STDC_IEC_60559_DFP__
(C23)
s'étend à 202311L si l'arithmétique à virgule flottante décimale IEC 60559 est prise en charge
(constante macro)
__STDC_IEC_60559_COMPLEX__
(C23)
s'étend à 202311L si l'arithmétique complexe IEC 60559 est prise en charge
(constante macro)
__STDC_IEC_60559_TYPES__
(C23)
s'étend à 202311L si les types d'échange et étendus IEC 60559 sont pris en charge
(constante macro)

Les valeurs de ces macros (à l'exception de __FILE__ et __LINE__ ) restent constantes tout au long de l'unité de traduction. Toute tentative de redéfinir ou de supprimer ces macros entraîne un comportement indéfini.

La variable prédéfinie __func__ (voir définition de fonction pour plus de détails) n'est pas une macro de préprocesseur, même si elle est parfois utilisée conjointement avec __FILE__ et __LINE__ , par exemple par assert .

(depuis C99)

Exemple

#include <stdio.h>
// make function factory and use it
#define FUNCTION(name, a) int fun_##name(int x) { return (a) * x; }
FUNCTION(quadruple, 4)
FUNCTION(double, 2)
#undef FUNCTION
#define FUNCTION 34
#define OUTPUT(a) puts( #a )
int main(void)
{
    printf("quadruple(13): %d\n", fun_quadruple(13));
    printf("double(21): %d\n", fun_double(21));
    printf("%d\n", FUNCTION);
    OUTPUT(billion); // note the lack of quotes
}

Sortie :

quadruple(13): 52
double(21): 42
34
billion

Rapports de défauts

Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C publiées précédemment.

DR Applicable à Comportement publié Comportement corrigé
DR 321 C99 il n'était pas clair si L 'x' == 'x' était toujours vrai
parmi le jeu de caractères de base
__STDC_MB_MIGHT_NEQ_WC__ ajouté à cet effet

Références

  • Norme C23 (ISO/CEI 9899:2024) :
  • 6.10.4 Remplacement de macro (p : 187-184)
  • 6.10.9 Noms de macros prédéfinis (p : 186-188)
  • Norme C17 (ISO/CEI 9899:2018) :
  • 6.10.3 Remplacement de macro (p: 121-126)
  • 6.10.8 Noms de macros prédéfinis (p: 127-129)
  • Norme C11 (ISO/IEC 9899:2011) :
  • 6.10.3 Remplacement de macro (p: 166-173)
  • 6.10.8 Noms de macros prédéfinis (p: 175-176)
  • Norme C99 (ISO/CEI 9899:1999) :
  • 6.10.3 Remplacement de macro (p : 151-158)
  • 6.10.8 Noms de macros prédéfinis (p : 160-161)
  • Norme C89/C90 (ISO/IEC 9899:1990):
  • 3.8.3 Remplacement de macro
  • 3.8.8 Noms de macro prédéfinis

Voir aussi

Documentation C++ pour Remplacer les macros de texte