Использование макрокоманды в макрофункции на C

#c #macros #c-preprocessor

Вопрос:

Использование #ifdef <macro> <statement> #endif позволяет отображать подробные сообщения только во время разработки и довольно удобно. Интересно, возможно ли что-то вроде приведенного ниже кода, став еще короче:

 // pseudo-code:

#define IN_DEV
#define DEBUG_ONLY(statement) (#ifdef IN_DEV (statement) #endif)

int main(void)
{
   DEBUG_ONLY(printf("hello from debug moden");)
   //...
}
 

Это стоило бы мне только очень читаемого однострочника, который можно включить или выключить. Возможно ли что-то подобное / близкое к этому?

Ответ №1:

Нет особого смысла передавать целые выражения в качестве параметров в макросы. Это и опасно, и недостижимо. Что еще хуже, это ведет нас по пути запутывания «давайте изобретем наш собственный частный макроязык вместо использования читаемого C, который может понять любой». Это ужасная идея даже для целей отладки.

Более разумным подходом был бы функциональный макрос печати, который печатает что-то только в отладочной сборке.

 #ifdef INDEV
  #define DEBUG_PRINT(...) printf(__VA_ARGS__)
#else
  #define DEBUG_PRINT(...)
#endif

int main(void)
{
   DEBUG_PRINT("hello from debug moden");
}
 

При желании этот макрос можно сузить, чтобы принимать только строки, и сделать его более безопасным для типов (только C17):

 #ifdef INDEV
  #define DEBUG_PRINT(str) _Generic((str), char*: puts(str))
#else
  #define DEBUG_PRINT(str) _Generic((str), char*: (void)0)
#endif
 

Ответ №2:

Вы могли бы изменить значение DEBUG_ONLY зависимого от того, определено ли оно IN_DEV :

 // pseudo-code:

#ifdef IN_DEV
#define DEBUG_ONLY(statement) {statement}
#else
#define DEBUG_ONLY(statement) // Nothing
#endif

int main(void)
{
   DEBUG_ONLY(printf("hello from debug moden");)
   //...
}

 

Пример выполнения: Ссылка

Комментарии:

1. Очень умно, спасибо!

Ответ №3:

Это невозможно. Вы не можете использовать #if внутри определения макроса.

Что вы можете сделать, так это:

 #define IN_DEV

#ifdef
 #define DEBUG_ONLY(statement) (statement)
#else
 #define DEBUG_ONLY(statement)
#endif

int main(void)
{
   DEBUG_ONLY(printf("hello from debug moden");)
   //...
}
 

Это также можно переключать только с помощью одного макроса IN_DEV .