$ cat xx.c
#define VARIABLE 3
#define PASTER(x,y) x ## _ ## y
#define EVALUATOR(x,y) PASTER(x,y)
#define NAME(fun) EVALUATOR(fun, VARIABLE)
extern void NAME(mine)(char *x);
$ gcc -E xx.c
# 1 "xx.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "xx.c"
extern void mine_3(char *x);
$
Cade Roux a demandé pourquoi ce besoin de deux niveaux d'indirection. Le désinvolte réponse est parce que la norme impose de le travail; vous avez tendance à trouver vous avez besoin de l'équivalent truc avec la stringizing opérateur de trop.
L'article 6.10.3 du standard C99 couvre macro "remplacement", et 6.10.3.1 couvre l'argument de substitution".
Après les arguments en faveur de l'invocation d'une fonction-comme macro ont été identifiés,
l'argument de la substitution a lieu. Un paramètre dans la liste de remplacement, que si elle est précédée
par un #
ou ##
prétraitement jeton ou suivie par un ##
prétraitement jeton (voir ci-dessous), est
remplacé par l'argument correspondant après toutes les macros qui y sont contenues ont été
élargi. Avant d'être remplacé chaque argument du prétraitement des jetons
complètement macro remplacé comme si elles constituaient le reste de la prétraitement fichier; pas d'autres
prétraitement des jetons sont disponibles.
Dans l'invocation NAME(mine)
, l'argument est "mien"; il est complètement déployée "mien"; il est alors remplacé par la chaîne de remplacement:
EVALUATOR(mine, VARIABLE)
Maintenant la macro ÉVALUATEUR est découvert, et les arguments sont isolés comme "mien" et "VARIABLE"; ce dernier est ensuite élargi à '3', et remplacé par la chaîne de remplacement:
PASTER(mine, 3)
Le fonctionnement de ce qui est couvert par d'autres règles (6.10.3.3 '# # opérateur"):
Si, dans la liste de remplacement d'une fonction-comme macro, un paramètre est immédiatement précédée
ou suivie par un ##
prétraitement jeton, le paramètre est remplacé par le correspondant
l'argument de prétraitement jeton de séquence; [...]
Pour à la fois objet et la fonction-comme macro invocations, avant le remplacement de la liste est
revu pour plus de noms de macro pour remplacer, chaque instance d'un ##
prétraitement jeton
dans la liste de remplacement (pas d'argument) est supprimé et le précédent prétraitement
jeton est concaténé avec la suite de prétraitement jeton.
Ainsi, la liste de remplacement contient x
suivie par ##
et également ##
suivie par y
; nous avons donc:
mine ## _ ## 3
et l'élimination de l' ##
des jetons et de la concaténation des jetons sur chaque côté combine 'mine' avec '_' et '3', pour obtenir:
mine_3
C'est le résultat souhaité.
Si nous examinons la question d'origine, le code a été adapté à l'usage "mine" au lieu de "une_fonction'):
#define VARIABLE 3
#define NAME(fun) fun ## _ ## VARIABLE
NAME(mine)
L'argument de NOM est clairement le "mien" et qui est entièrement développée.
En suivant les règles de 6.10.3.3, nous trouvons:
mine ## _ ## VARIABLE
qui, lorsque l' ##
des opérateurs sont éliminés, les cartes à:
mine_VARIABLE
exactement comme indiqué dans la question.