2010-05-14 44 views
34

Quiero escribir una macro que escupe código basado en el valor booleano de su parámetro. Así que digamos que DEF_CONST(true) debería expandirse a const, y DEF_CONST(false) debería expandirse a nada.Preprocesador C: usando #if dentro #define?

Es evidente que el siguiente no funciona porque no podemos utilizar otro preprocesador dentro #defines:

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

Cualquier idea acerca de cómo hacerlo?

+4

¿Cuál es el punto de esto? ¿Tiene un ejemplo concreto, porque esto parece bastante extraño ... –

+0

Véase también . – Rhubbarb

Respuesta

44

Puede simular condicionales utilizando macro token concatenation de la siguiente manera:

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

Entonces,

/* 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 */ 

también, lo que permite el paso de parámetros macro a DEF_CONST en sí (como se señala correctamente GMan y otros):

#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 */ 

También puede considerar el mucho simp ler (aunque potencialmente menos flexible):

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

Typo en el anterior, simplemente se perdió la marca de edición. Debe ser '#define DEF_CONST (b_const) CONCATENATE (DEF_CONST_, b_const)'. – GManNickG

+2

Yup - Tokening o stringizing ('' ## ''o' '#'') operadores de preprocesador casi siempre necesitan un nivel de direccionamiento indirecto para funcionar como se desee: http://stackoverflow.com/questions/1767683/c- programación-preprocesador-macros-como-tokens/1769037 # 1769037 –

5

Hacerlo como una macro paramterizada es un poco extraño.

¿Por qué no hacer algo como esto:

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

entonces usted puede escribir código como este:

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

y si se compila con USE_CONST definido (por ejemplo, normalmente algo -DUSE_CONST en el makefile o opciones del compilador) luego usará las constelaciones, de lo contrario no lo hará.

Editar: En realidad veo Vlad cubierto esa opción al final de su respuesta, por lo que para él :) 1