Voici un exemple pertinent. Ce n'est évidemment pas valide C, mais j'ai juste affaire au préprocesseur ici, donc le code n'a pas réellement à compiler.Lors de l'expansion de macro C, existe-t-il un cas spécial pour les macros qui s'étendent à "/ *"?
#define IDENTITY(x) x
#define PREPEND_ASTERISK(x) *x
#define PREPEND_SLASH(x) /x
IDENTITY(literal)
PREPEND_ASTERISK(literal)
PREPEND_SLASH(literal)
IDENTITY(*pointer)
PREPEND_ASTERISK(*pointer)
PREPEND_SLASH(*pointer)
course à pied préprocesseur de gcc sur elle:
gcc -std=c99 -E macrotest.c
Cela donne:
(...)
literal
*literal
/literal
*pointer
**pointer
/*pointer
S'il vous plaît noter l'espace supplémentaire dans la dernière ligne. Cela ressemble à une fonctionnalité pour empêcher les macros de s'étendre vers "/ *", ce qui, je suis sûr, est bien intentionné. Mais en un coup d'œil, je n'ai rien trouvé de ce comportement dans la norme C99. Là encore, je suis inexpérimenté au C. Quelqu'un peut-il nous éclairer à ce sujet? Où est-ce spécifié? J'imagine qu'un compilateur adhérant à C99 ne devrait pas simplement insérer des espaces supplémentaires pendant l'expansion de macro juste parce qu'il empêcherait probablement des erreurs de programmation.
+1. Je pense que l'idée clé est que la sortie de -E n'est en effet pas spécifiée par la norme.La norme parle du programme constitué d'une séquence de jetons de prétraitement, puis plus tard, il est converti en une séquence de jetons. Il revient entièrement au préprocesseur de représenter ces séquences, et dans ce cas comment les sérialiser en un fichier sous la forme d'une séquence de * octets *. Bien sûr, la seule sérialisation viable est celle qui sera lue comme une série équivalente de jetons de prétraitement, de sorte que, comme vous le dites, elle doit mettre des espaces entre deux jetons qui ensemble formeraient un. –
Je suis d'accord à 100%, je voulais écrire quelque chose comme votre explication, mais je n'ai pas eu le temps. –
Bonne réponse, même si j'ai deux commentaires nitpicky: Il n'y a pas de jeton '/ *'; les commentaires sont supprimés de la source avant d'être marqués. Vous pouvez former un jeton «++» à partir de deux jetons «+» en utilisant «##». –