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

0

У меня есть вопрос. В одном из моих проектов я использую 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

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

Благодаря,

Теги:
macros
debug-print

3 ответа

2

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

#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.

  • 0
    Спасибо .. это сработало .. :)
1

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

#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)

  • 0
    Спасибо .. это сработало ..
  • 0
    Иногда это может вести себя очень странно. Подумайте, if (x) ON_DEBUG( printf("hello"); printf("world"); ) else something(); , Это if бы подхватил только первый принтф. Вместо этого вы должны выполнить #define ON_DEBUG(X,...) do { X,__VA_ARGS__ }while(0)
Показать ещё 1 комментарий
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;
}

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню