2009-11-06 4 views
2

code:Pourquoi la sortie des deux instructions suivantes est-elle différente?

#define f(a,b) a##b 
#define g(a) #a 
#define h(a) g(a) 

main() 
{ 
     printf("%s\n",h(f(1,2))); //[case 1] 
     printf("%s\n",g(f(1,2))); //[case 2] 
} 

sortie:

12 
f(1, 2) 

Pourquoi la sortie ne même dans les deux cas?

[Je compris la concaténation (a##b) et la conversion de chaînes (#a) here, mais je n'ai pas pourquoi la sortie est différente dans les deux cas.]

+0

Quelle plate-forme de compilateur utilisez-vous? Je ne serais pas surpris si ce comportement est spécifique au compilateur. –

+0

J'utilise 'Cygwin gcc' sous Windows. – Moeb

Répondre

6

La partie pertinente de la spécification est:

6.10.3.1

« Après les arguments en faveur de l'invocation d'une macro fonction semblable ont été identifiés, la substitution des arguments a lieu un paramètre. la liste de remplacement, à moins qu'elle ne soit précédée de par un jeton de prétraitement # ou ## ou suivie d'un jeton de prétraitement ## (voir ci-dessous), est remplacée par l'argument correspondant après que toutes les macros contenues dans celle-ci ont été étendues. En d'autres termes, lorsque les paramètres de macro sont remplacés, il y a d'abord un cycle de macro-expansion sur l'argument, , sauf si le paramètre apparaît aveC# ou ##.

Donc g(blah) juste stringifie blah. h(blah) première macro-développe blah, puis le stripe.

La différence est particulièrement pertinente lorsque vous souhaitez stringify noms de macro:

printf("The value of the " g(NULL) " macro is " h(NULL)); 
+0

@onebyone merci de citer la spécification. – Moeb

1

Ceci est probablement l'ordre d'évaluation. Dans le premier cas, h et f sont évalués dans le premier passage à g et 12. Le deuxième passage de macro-évaluation convertit alors cela en 12. Dans le second cas, g évalue directement f (1,2) dans une chaîne.

+0

oui, je comprends cela. Mais pourquoi cela se passe-t-il comme vous venez de le mentionner? – Moeb

0

Les macros C ne sont pas des fonctions. C'est une simple substitution de texte. Il suffit de remplacer un en g (a) avec "f (1, 2)" et c'est votre réponse.

+0

donc dans 'case1',' h (f (1,2)) 'devient' g (f (1,2)) '. Donc, les résultats devraient être les mêmes! – Moeb

+0

Non puisque les paramètres après # ne sont pas développés. – ihuk

1

Quand une macro de style fonction est étendue, toutes les instances de paramètres dans la liste de remplacement qui ne sont pas précédés d'un # ou immédiatement adjacentes à un ## sont remplacées par l'argument correspondant après la macro-expansion. Macro expansion ne se produit pas pour les paramètres qui suivent un # ou sont adjacents à un ##. S'il reste des macros dans l'expansion, la macro-expansion se produit récursivement sur le remplacement jusqu'à ce qu'il n'y ait plus de macros. (L'expansion de toute macro ne se développer au cours de son expansion à tout niveau d'imbrication de sorte que vous ne pouvez pas obtenir une récursion infinie.)

Dans votre exemple, g(f(1,2)) devient # de f(1,2) (pas d'expansion de l'argument macro) qui est "f (1, 2)", une chaîne littérale.

h(f(1,2)) devient g(12) parce que l'expansion macro f(1,2) subit, il y a une macro qui reste dans cette expansion, donc c'est dilatée à nouveau et g(12) devient « 12 ».

Questions connexes