web-dev-qa-db-fra.com

Comment fonctionne exactement l'astuce de double chaîne?

Au moins certains [~ # ~] c [~ # ~] préprocesseurs vous permettent de chaîne la valeur d'une macro, plutôt que son nom, en la passant à travers une macro de type fonction à une autre qui la stringise:

#define STR1(x) #x
#define STR2(x) STR1(x)
#define THE_ANSWER 42
#define THE_ANSWER_STR STR2(THE_ANSWER) /* "42" */

Exemples de cas d'utilisation ici .

Cela fonctionne, au moins dans GCC et Clang (les deux avec -std=c99), mais je ne suis pas sûr comment cela fonctionne en termes C-standard.

Ce comportement est-il garanti par C99?
Si oui, comment C99 le garantit-il?
Sinon, à quel moment le comportement passe-t-il de C à GCC?

81
Peter Hosey

Oui, c'est garanti.

Cela fonctionne parce que les arguments des macros sont eux-mêmes développés par macro, sauf où le nom de l'argument de macro apparaît dans le corps de la macro avec le stringifier # ou le token-paster ##.

6.10.3.1/1:

... Après que les arguments pour l'appel d'une macro de type fonction ont été identifiés, la substitution d'argument a lieu. Un paramètre de la liste de remplacement, sauf s'il est précédé d'un jeton de prétraitement # ou ## ou suivi d'un jeton de prétraitement ## (voir ci-dessous), est remplacé par l'argument correspondant une fois que toutes les macros qu'il contient ont été développées ...

Donc, si vous faites STR1(THE_ANSWER) alors vous obtenez "THE_ANSWER", car l'argument de STR1 n'est pas macro-développé. Cependant, l'argument de STR2 est macro-développé lorsqu'il est substitué dans la définition de STR2, ce qui donne donc à STR1 un argument de 42, avec le résultat "42".

77
Steve Jessop

Comme le note Steve, cela est garanti, et il est garanti depuis la norme C89 - qui était la norme codifiée les opérateurs # et ## dans les macros et les mandats récursivement. développer les macros dans les arguments avant de les remplacer dans le corps si et seulement si le corps n'applique pas # ou ## à l'argument. C99 est inchangé de C89 à cet égard.

20
Chris Dodd