Question

Pourquoi ces blocs de code à des résultats différents?

Certains de code commune:

#define PART1PART2 works
#define STRINGAFY0(s) #s
#define STRINGAFY1(s) STRINGAFY0(s)

cas 1:

#define GLUE(a,b,c) a##b##c  
STRINGAFY1(GLUE(PART1,PART2,*))
//yields
"PART1PART2*"

cas 2:

#define GLUE(a,b) a##b##*
STRINGAFY1(GLUE(PART1,PART2))
//yields
"works*"

cas 3:

#define GLUE(a,b) a##b
STRINGAFY1(GLUE(PART1,PART2*))
//yields
"PART1PART2*"

Je suis à l'aide de MSVC++ à partir de VS.net 2005 sp1

Edit:actuellement, il est ma conviction que le préprocesseur les œuvres de ce genre lors de l'expansion des macros:Étape 1:- prendre le corps - supprimer tout l'espace autour d' ## les opérateurs - analyser la chaîne, dans le cas d'un identificateur est trouvé qui correspond au nom d'un paramètre:-si c'est à côté d'un ## opérateur, remplacer l'identifiant à la valeur littérale du paramètre (c'est à direla chaîne de caractères passée en) -si elle n'est PAS à côté d'un ## opérateur, exécuter toute cette explication sur la valeur du paramètre d'abord, puis de remplacer l'identifiant à ce résultat.(en ignorant les stringafy unique '#' cas atm) -supprimer tous les ## les opérateurs

Étape 2:- prendre que la chaîne résultante et l'analyse de toutes les macros

maintenant, à part que je crois que tous les 3 cas devrait produire exactement la même chaîne résultante:

PART1PART2*

et donc après l'étape 2 de suite dans

œuvres*

mais à tout le moins, devrait aboutir à la même chose.

Était-ce utile?

La solution

les cas 1 et 2 n'ont pas défini de comportement depuis votre tente de coller un * dans un préprocesseur jeton.Selon les règles d'association de votre préprocesseur ce soit essaie de coller ensemble les jetons PART1PART2 (ou tout simplement PART2) et *.Dans votre cas, c'est probablement ce qui échoue silencieusement, qui est l'un des résultats possibles quand les choses ne sont pas définis.Le jeton PART1PART2 suivie par * ne seront pas considérés comme des macro-expansion de nouveau.Stringfication donne le résultat que vous voyez.

Mon gcc se comporte différemment sur votre exemples:

/usr/bin/gcc -O0 -g -std=c89 -pedantic   -E test-prepro.c
test-prepro.c:16:1: error: pasting "PART1PART2" and "*" does not give a valid preprocessing token
"works*"

Donc, pour résumer votre cas 1 a deux problèmes.

  • Collage de deux jetons qui n'étaient pas le résultat valide préprocesseur jeton.
  • ordre d'évaluation de la ## opérateur

Dans le cas 3, votre compilateur est de donner un mauvais résultat.Il devrait

  1. évaluer les arguments pour STRINGAFY1
  2. pour cela, il doit développer GLUE
  3. GLUE résultats dans PART1PART2*
  4. qui doit être élargi encore
  5. le résultat est works*
  6. qui est ensuite passé à STRINGAFY1

Autres conseils

Cela fait exactement ce que vous dites de le faire.Les premier et seconde prennent les noms de symboles passés et collez-les dans un nouveau symbole.Le troisième prend 2 symboles et les colle, puis vous placez le * dans la chaîne vous-même (ce qui sera éventuellement évalué dans quelque chose d'autre.)

Quelle est exactement la question avec les résultats?Qu'attendez-vous d'obtenir?Tout semble fonctionner comme je m'y attendrais.

Alors bien sûr, c'est la question de savoir pourquoi jouez-vous avec les arts sombres du symbole muning comme celui-ci de toute façon?:)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top