Je le sais:
#define foo 4
#define str(s) #s
avec str(foo)
écrit: "foo"
, car stringify est exécuté en premier lieu de l'expansion du texte, mais ceci:
#define xstr(s) str(s)
#define str(s) #s
#define foo 4
avec xstr(foo)
écrit: "4"
.
Pourquoi? Quelles sont les étapes du processus?
Les étapes pertinentes de l'expansion des macros sont (selon C 2011 [n1570] 6.10.3.1 et C++ 1998 16.3.1):
#
Ou ##
.Ainsi, avec xstr(foo)
, nous avons:
str(s)
, ne contient ni #
Ni ##
, Donc rien ne se passe.foo
est remplacé par 4
, C'est donc comme si xstr(4)
avait été utilisé.str(s)
, le paramètre s
est remplacé par 4
, Produisant str(4)
.str(4)
est à nouveau analysé. (Les étapes résultantes produisent ”4”
.)Notez que le problème avec str(foo)
est que l'étape 2, qui remplacerait foo
par 4
, Vient après l'étape 1, qui change l'argument en chaîne. À l'étape 1, foo
est toujours foo
; il n'a pas été remplacé par 4
, le résultat est donc ”foo”
.
C'est pourquoi une macro d'aide est utilisée. Il nous permet d'obtenir une étape 2, puis d'utiliser une autre macro pour effectuer l'étape 1.
str(foo)
: remplacer str(foo)
par #foo
, C'est-à-dire "foo"
xstr(foo)
: remplacer xstr(foo)
par str(<foo-value>)
, c'est-à-dire str(4)
str(4)
: remplacer str(4)
par #4
, C'est-à-dire "4"
le préprocesseur évalue les macro-fonctions développant les macro-variables, jusqu'à ce qu'il n'y ait rien à évaluer:
Si vous définissez
#define xstr(s) str(s) + 1
#define str(s) s + 1
dans le code suivant
#define foo 4
int main()
{
std::cout << str(foo) << '\n'
<< xstr(foo) << '\n' ;
}
il évaluerait comme
str(foo)
par <foo-value> + 1
, C'est-à-dire 4 + 1
Et le résultat est 4 + 1
xstr(foo)
par str(<foo-value>) + 1
, c'est-à-dire str(4) + 1
str(4)
par <4-value> + 1
, C'est-à-dire 4 + 1
Et le résultat est 4 + 1 + 1