У меня есть вопрос. В одном из моих проектов я использую FLAG PRINT для включения/выключения отладки printfs. в настоящее время я использую что-то вроде этого.
#ifdef PRINT
printf("DEBUG");
#endif
Это боль, чтобы поместить этот #ifdef перед каждым printf. Поэтому я думал, что для #ifdef есть #define, что-то вроде
#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
-statements, см. комментарий Aaron McDaid)
if (x) ON_DEBUG( printf("hello"); printf("world"); ) else something();
, Это if
бы подхватил только первый принтф. Вместо этого вы должны выполнить #define ON_DEBUG(X,...) do { X,__VA_ARGS__ }while(0)
Я бы сделал это совсем по-другому. Сначала определите флаг, который включает или выключает печать:
// 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;
}
В оптимизированных сборках, где флаг не определен, большинство (если не все) кода будут оптимизированы.