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

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

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

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

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

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

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

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

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

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

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

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

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

  • Что такое хорошая ссылочная документирование шаблонов использования X-Macros в C (или, возможно, C ++)?
  • Сначала препроцессор C комментирует или расширяет macros?
  • objective-C: декларация о перекрестном classе
  • Расширение макроскопического расширения MSVC ++
  • Объединение C ++ и C - как работает #ifdef __cplusplus?
  • Представление больших чисел в исходном коде для удобочитаемости?
  • Номер строки C / C ++
  • Можно ли перебирать аргументы в переменных массивах?
  • Макро против функции в C
  • Существуют ли какие-либо macros, чтобы определить, скомпилирован ли мой код для Windows?
  • MSVC не расширяет __VA_ARGS__ правильно
  • Давайте будем гением компьютера.