2014-05-14 4 views
1

je suis tombé sur un autre morceau de code qui est encore plus déroutant ..Macro dans les macro ne fonctionne pas

#include "stdio.h" 

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

#define g(a) #a 

#define h(a) g(a) 

int main(void) 
{ 
    printf("%s\n",h(f(1,2))); 
    printf("%s\n",g(1)); 
    printf("%s\n",g(f(1,2))); 
    return 0; 
} 

sortie est

12 

1 

f(1,2) 

Mon hypothèse a été 1) premier f(1,2) est remplacé par 12, en raison de la macro f(a,b) concène ses arguments 2) puis g(a) macro remplace 1 par un litre de chaîne al "1" 3), la sortie doit être 1

Mais pourquoi ne pas se g(f(1,2)) substitué à 12. Je suis sûr qu'il me manque quelque chose ici. Quelqu'un peut-il m'expliquer ce programme?

+3

car g est évalué avant f, ce qui convertit 'f (1,2)' en un littéral de chaîne. –

+2

Vous dites C dans le titre (dont vous n'avez pas besoin), mais tag C++? Probablement pas différent pour cela, mais vous devriez être cohérent. – crashmstr

Répondre

2

remplacement Macro se produit à partir de l'extérieur. (Au sens strict, le préprocesseur doit se comporter comme si elle remplace macros un à la fois, à partir du début du fichier et de redémarrer après chaque remplacement.)

la norme (C99 §6.10.3.2/2) dit

Si, dans la liste de remplacement, un paramètre est immédiatement précédé par un # prétraiter jeton, les deux sont remplacés par une seule chaîne de caractères jeton de pré-traitement littéral contient l'orthographe de la séquence de jetons de prétraitement pour l'argument correspondant.

Depuis # est présent dans la liste de remplacement pour la g macro, l'argument f(1,2) est converti en une chaîne immédiatement, et le résultat est "f(1,2)".

D'autre part, dans h(f(1,2)), puisque la liste de remplacement ne contient pas #, §6.10.3.1/1 applique,

Après les arguments en faveur de l'invocation d'une macro de fonction ont été comme identifié, la substitution d'argument a lieu.Un paramètre dans la liste de remplacement, à moins que précédé par un # ou ## prétraiter jeton ou suivi d'un pré-traitement ## jeton (voir ci-dessous), est remplacé par l'argument correspondant après que toutes les macros qui y sont contenues ont été élargi.

et l'argument est f(1, 2) macro étendre pour donner 12, donc le résultat est g(12) qui devient alors "12" lorsque le fichier est « re-scanné ».

1

Les macros ne peuvent pas être développées dans des directives de prétraitement. De C99 6.10.3.4/3 « Réanalyse et le remplacement plus »:

Le résultat prétraiter complètement macro-séquence jeton remplacé n'est pas traitée comme une directive de pré-traitement, même si elle ressemble à un ,

Source: https://stackoverflow.com/a/2429368/2591612

Mais vous pouvez appeler f(a,b) de g comme vous l'avez fait avec h. f(a,b) est interprété comme un littéral de chaîne sous la forme @Red Alert.