У меня вопрос. В одном из моих проектов я использую 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
но это дает ошибку компилятора. Можете ли вы сказать мне, чтобы упростить.
Спасибо,
Стандартный способ
#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
пункт.
Как насчет заголовка с
#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") );
( do
—while
вынуждает вас добавить последнюю точку с запятой и защищает оператор в случаях если (вложенный) if
, см. комментарий Аарона МакДейда)
Я бы на самом деле сделал это совсем по-другому. Сначала определите флаг, который включает или выключает печать:
// 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;
}
В оптимизированных сборках, где флаг не определен, большая часть (если не весь) кода будет оптимизирована.