условное производное использование макроса в cpp

У меня вопрос. В одном из моих проектов я использую FLAG PRINT для включения / выключения отладки printfs. В настоящее время я использую что-то вроде этого.

#ifdef PRINT
printf("DEBUG");
#endif

Больно ставить этот #ifdef перед каждым printf. Так что я думал, что #define для #ifdef, что-то вроде

#define DEBUG_PRINT
#define PRINT (#ifdef DEBUG_PRINT)
#define ENDPRINT #endif

так что я могу использовать как

PRINT
printf("DEBUG");
ENDPRINT

но это дает ошибку компилятора. Можете ли вы сказать мне, чтобы упростить.

Спасибо,

0

Решение

Стандартный способ

#ifdef DEBUG_PRINT
#  define is_debug() (1)
#else
#  define is_debug() (0)
#endif

#define pr_dbg(fmt, ...) do { \
if (is_debug()) \
printf(fmt, __VA_ARGS__); \
} while (0)

При использовании gcc вы можете / должны написать

            printf(fmt, ## __VA_ARGS__);

иметь дело с пустыми аргументами.

В своем коде вы можете написать тогда

pr_dbg("foo=%u\n", foo);

Оптимизатор выбросит выражение, когда DEBUG_PRINT не определен, но ваши операторы отладки будут по-прежнему проверяться на наличие синтаксических ошибок. Это позволяет избежать тихой поломки, когда, например, неопределенные переменные используются внутри #ifdef пункт.

2

Другие решения

Как насчет заголовка с

#ifdef DEBUG
#define ON_DEBUG(X,...) do { X, __VA_ARGS__; } while( false )
#else
#define ON_DEBUG(X,...) do {} while( false )
#endif

и в своем коде вы просто используете

ON_DEBUG( printf("Hallo, %s", "Welt") );

( dowhile вынуждает вас добавить последнюю точку с запятой и защищает оператор в случаях если (вложенный) if, см. комментарий Аарона МакДейда)

1

Я бы на самом деле сделал это совсем по-другому. Сначала определите флаг, который включает или выключает печать:

// uncomment to turn off debug printing
#define DEBUG_PRINT 1

Затем условно определите макрос вашего принтера в зависимости от состояния определения DEBUG_PRINT:

#ifdef DEBUG_PRINT
#define PRINT (X) (printf(x))
#else
#define PRINT (x)
#endif

Который может быть использован просто как:

PRINT("foo");

Но на самом деле я бы вообще ничего не делал. Вместо этого у меня будет флаг включения / выключения, как указано выше, а затем учебный класс что делает печать:

// comment out to not do debug printing
//#define DEBUG_PRINTING 1

#ifdef DEBUG_PRINTING
class Printer
{
public:
Printer() {}
~Printer()
{
std::cout << mOutput.str() << "\n";
}

template <typename TYPE> Printer& operator<< (const TYPE& val)
{
mOutput << val;
return * this;
}
template <size_t N> Printer& operator<<  (const char(&ary)[N])
{
mOutput << ary;
return * this;
}
private:
std::stringstream mOutput;
};
#else
class Printer
{
public:
Printer() {};
template <typename TYPE> Printer& operator<< (const TYPE& val)
{
return * this;
}
template <size_t N> Printer& operator<< (const char(&ary)[N])
{
return * this;
}
};
#endif

int main()
{
Printer() << "My output here. " << 42;
}

В оптимизированных сборках, где флаг не определен, большая часть (если не весь) кода будет оптимизирована.

0
По вопросам рекламы [email protected]