2010-05-14 6 views
34

Je veux écrire une macro qui crache le code basé sur la valeur booléenne de son paramètre. Donc disons DEF_CONST(true) devrait être étendu en const, et DEF_CONST(false) devrait être étendu en rien.Préprocesseur C: utiliser #if dans #define?

Il est clair que ce qui suit ne fonctionne pas parce que nous ne pouvons pas utiliser un autre préprocesseur intérieur #defines:

#define DEF_CONST(b_const) \ 
#if (b_const) \ 
    const \ 
#endif 

Toute idée sur la façon de le faire?

+4

Quel est le point de tout cela? Avez-vous un exemple concret, car cela semble plutôt étrange ... –

+0

Voir aussi . – Rhubbarb

Répondre

44

Vous pouvez simuler conditionals à l'aide macro token concatenation comme suit:

#define DEF_CONST(b_const) DEF_CONST_##b_const 
#define DEF_CONST_true const 
#define DEF_CONST_false 

Ensuite,

/* OK */ 
DEF_CONST(true) int x; /* expands to const int x */ 
DEF_CONST(false) int y; /* expands to int y */ 

/* NOT OK */ 
bool bSomeBool = true;  // technically not C :) 
DEF_CONST(bSomeBool) int z; /* error: preprocessor does not know the value 
           of bSomeBool */ 

En outre, ce qui permet de passer des paramètres macro se DEF_CONST (comme l'a fait correctement par GMan et d'autres):

#define DEF_CONST2(b_const) DEF_CONST_##b_const 
#define DEF_CONST(b_const) DEF_CONST2(b_const) 
#define DEF_CONST_true const 
#define DEF_CONST_false 

#define b true 
#define c false 

/* OK */ 
DEF_CONST(b) int x;  /* expands to const int x */ 
DEF_CONST(c) int y;  /* expands to int y */ 
DEF_CONST(true) int z; /* expands to const int z */ 

Vous pouvez également considérer le beaucoup simp ler (bien que potentiellement moins flexible):

#if b_const 
# define DEF_CONST const 
#else /*b_const*/ 
# define DEF_CONST 
#endif /*b_const*/ 
+0

Typo dans le ci-dessus, juste raté la marque d'édition. Devrait être '#define DEF_CONST (b_const) CONCATENATE (DEF_CONST_, b_const)'. – GManNickG

+2

Yup - le collage de jetons ou le chaînage (opérateurs de préprocesseur '## '' ou '# #') nécessite presque toujours un niveau d'indirection pour fonctionner comme vous le souhaitez: http://stackoverflow.com/questions/1767683/c- programmation-preprocessor-macros-as-tokens/1769037 # 1769037 –

5

Le faire comme une macro paramétrée est un peu étrange.

Pourquoi ne pas simplement faire quelque chose comme ceci:

#ifdef USE_CONST 
    #define MYCONST const 
#else 
    #define MYCONST 
#endif 

Ensuite, vous pouvez écrire du code comme ceci:

MYCONST int x = 1; 
MYCONST char* foo = "bar"; 

et si vous compilez avec USE_CONST défini (par exemple en général quelque chose -DUSE_CONST dans le makefile ou options du compilateur) alors il utilisera les consts, sinon ce ne sera pas le cas.

Edit: En fait, je voir Vlad couvert cette option à la fin de sa réponse, donc +1 pour lui :)

Questions connexes