Replacing text macros
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
#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
#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 :
|
|
__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
|
(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
|