Подтвердить что ты не робот

Как использовать #if внутри #define в препроцессоре C?

Я хочу написать макрос, который выплевывает код на основе логического значения его параметра. Так что DEF_CONST(true) следует развернуть в const, а DEF_CONST(false) следует развернуть в ничто.

Очевидно, что следующее не работает, потому что мы не можем использовать другой препроцессор внутри #defines:

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

Ответ 1

Вы можете имитировать условные выражения, используя конкатенацию макросов маркеров следующим образом:

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

Затем

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

Кроме того, разрешая передачу параметров макроса самому DEF_CONST (как правильно указано GMan и другими):

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

Вы также можете рассмотреть гораздо более простой (хотя и менее гибкий):

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

Ответ 2

Выполнение этого как макрокоманды с параметрами немного нечетно.

Почему бы просто не сделать что-то вроде этого:

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

Затем вы можете написать код следующим образом:

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

и если вы скомпилируете с USE_CONST определенным (например, что-то -DUSE_CONST в параметрах makefile или компилятора), то он будет использовать константы, иначе он не будет.

Изменить: На самом деле я вижу, что Влад закрыл этот вариант в конце своего ответа, поэтому +1 для него:)