2010-08-01 5 views
1

J'ai résolu mon problème avec cet extrait de code - mais il fait partie d'un programme plus vaste, donc je ne veux pas d'autre moyen de le faire - J'ai besoin d'un moyen de faire travail!Syntaxe de macros préprocesseur C++ bizarre

Quand je produis un fichier prétraité de ce code:

#define OUTER(a, b) \ 
    a##b 
#define INNER(c, d) \ 
    c##d 

enum foo { 
    OUTER(INNER(x, y), z) 
}; // line 108 

int APIENTRY _tWinMain(...) 
{ 
    foo bar = xyz; // line 112 
} 

je reçois:

enum foo { 
    xyz 
}; // line 108 

int __stdcall wWinMain(...) 
{ 
    foo bar = xyz; // line 112 
} 

qui est ce que je veux. Cependant, si je tente de compiler le code que je reçois:

erreur C2146: erreur de syntaxe: manquant '}' avant identifiant 'z' ligne 108
erreur C2143: erreur de syntaxe: manquant ';' avant '}' ligne 108
erreur C2143: erreur de syntaxe: manquant ';' avant '}' ligne 108
erreur C2059: erreur de syntaxe: '}' ligne 108
erreur C2065: 'xyz': ligne d'identification non déclarés 112

Je ne peux pas travailler dehors! Le problème semble être causé par le ## dans:

#define OUTER(a, b) \ 
    a##b 

mais pourquoi (et comment le réparer) est au-delà de moi ...

+0

@Jack Pourriez-vous expliquer ce que ## b est censé faire? Je n'ai jamais vu ça avant. – InsertNickHere

+1

@Insert C'est un opérateur de préprocesseur qui concatène littéralement ses deux arguments. Par exemple, 'OUTER (test, string)' dans l'extrait de code OP est remplacé par 'teststring' par le préprocesseur. –

+0

OK, je peux confirmer que cela se passe aussi dans gcc, et leur erreur est un peu plus descriptive. Il dit qu'il ne peut pas coller ')' et 'z' ensemble. Il me semble que le préprocesseur ne peut pas faire de pâtes imbriquées comme celle-ci, mais c'est une conjecture à ce stade. J'espère que ça aide un peu .. – Blindy

Répondre

9

Utilisez ce lieu:

#define CONCAT(X,Y) X##Y 
#define OUTER(a, b) CONCAT(a,b) 
#define INNER(a, b) CONCAT(a,b) 

enum foo { 
    OUTER(INNER(x, y),z) 
}; // line 108 

int main(...) 
{ 
    foo bar = xyz; // line 112 
} 
+0

Woo hoo ça marche! Mais pouvez-vous m'expliquer pourquoi cela fonctionne? Pourquoi ma sortie prétraite est-elle correcte? Je vois de l'erreur de gcc décrite ci-dessous qu'il semble garder un ")" et essayant de concaténer le "z" à "xy)"? Mais cela n'apparaît pas dans ma sortie pré-traitée! – Jack

+0

Lire la réponse canonique de Jonathan Leffler: http: // stackoverflow.com/questions/1489932/c-préprocesseur-et-concaténation –

+0

Ah! Est-ce que OUTER reçoit "INNER (c, d), z" et non "xy, z" comme je le pensais? Cela aurait du sens. Mais je ne comprends toujours pas pourquoi ma sortie prétraite est correcte! – Jack

1

Si vous utilisez gcc, vous pouvez lui donner l'option -E pour voir la sortie pré-traitée. Ensuite, vous pouvez facilement voir ce que le préprocesseur a sorti et comment déboguer vos macros. D'autres compilateurs ont également des options similaires.

2

Prétraitement votre exemple avec gcc résultats dans:

enum foo { 
t.c:7:1: error: pasting ")" and "z" does not give a valid preprocessing token 
    xy z 
}; 

qui devrait vous donner une idée de la raison pour laquelle la solution de Luther fonctionne et le vôtre ne fonctionne pas.