Подтвердить что ты не робот

Можете ли вы #define комментарий в C?

Я пытаюсь сделать отладочную систему, но, похоже, она не работает.

То, что я хотел выполнить, это примерно так:

#ifndef DEBUG
    #define printd //
#else
    #define printd printf
#endif

Есть ли способ сделать это? У меня много сообщений об отладке, и мне не понравится:

if (DEBUG)
    printf(...)

code

if (DEBUG)
    printf(...)

...
4b9b3361

Ответ 1

Нет, вы не можете. Комментарии удаляются из кода перед началом обработки директив предварительной обработки. По этой причине вы не можете включать комментарий в макрос.

Кроме того, никакие попытки "сформировать" комментарий позже с помощью какого-либо макроопределения не гарантируют работу. Компилятор не обязан распознавать комментарии "поздно" в качестве комментариев.

Лучший способ реализовать то, что вы хотите, - использовать макросы с переменными аргументами в C99 (или, возможно, используя расширения компилятора).

Ответ 2

Общим трюком является следующее:

#ifdef DEBUG
  #define OUTPUT(x) printf x
#else
  #define OUTPUT(x)
#endif

#include <stdio.h>
int main(void)
{   
  OUTPUT(("%s line %i\n", __FILE__, __LINE__));

  return 0;
}

Таким образом, у вас есть вся сила printf(), доступная вам, но вам приходится мириться с двойными скобками, чтобы заставить макрос работать.

Точка двойных скобок такова: вам нужен один набор, чтобы указать, что это вызов макроса, но вы не можете иметь неопределенное количество аргументов в макросе в C89. Однако, помещая аргументы в свой собственный набор скобок, они интерпретируются как один аргумент. Когда макрос расширяется, когда DEBUG определен, заменяющим текстом является слово printf, за которым следует сингл-аргумент, на самом деле это несколько элементов в скобках. Затем скобки интерпретируются как скобки, необходимые для вызова функции printf, поэтому все это работает.

Ответ 3

С99:

#ifdef DEBUG
    #define printd(...) printf(__VA_ARGS__)
#else
    #define printd(...)
#endif

Ну, для этого не требуется C99, но предполагает, что в версии для компилятора включена оптимизация:

#ifdef DEBUG
    #define printd printf
#else
    #define printd if (1) {} else printf
#endif

Ответ 4

Вы можете поместить весь свой отладочный вызов в функцию, позвоните ему printf_debug и поместите DEBUG внутри этой функции. Компилятор оптимизирует пустую функцию.

Ответ 5

В некоторых компиляторах (включая MS VS2010) это будет работать,

#define CMT / ## /

но нет грантополучателей для всех компиляторов.

Ответ 6

Стандартный способ - использовать

#ifndef DEBUG
    #define printd(fmt, ...)  do { } while(0)
#else
    #define printd(fmt, ...) printf(fmt, __VA_ARGS__)
#endif

Таким образом, когда вы добавляете точку с запятой в конец, она делает то, что вы хотите. Поскольку нет операции, компилятор будет компилировать "do... while"

Ответ 7

Непроверенные: Изменить: протестировано, используя его сейчас:)

#define DEBUG 1
#define printd(fmt,...) if(DEBUG)printf(fmt, __VA_ARGS__)

требуется не только определить DEBUG, но и дать ему значение non-zer0.

Приложение: Также хорошо работает с std::cout

Ответ 8

Как отметил Маккей, у вас возникнут проблемы, если вы просто попробуете заменить printd на //. Вместо этого вы можете использовать переменные макросы, чтобы заменить printd на функцию, которая ничего не делает, как в следующем.

#ifndef DEBUG
    #define printd(...) do_nothing()
#else
    #define printd(...) printf(__VA_ARGS__)
#endif

void do_nothing() { ; }

Использование отладчика, такого как GDB, тоже может помочь, но иногда достаточно быстрого printf.

Ответ 9

Я использую эту конструкцию много:

#define DEBUG 1
#if DEBUG
#if PROG1
#define DEBUGSTR(msg...)        { printf("P1: "); printf( msg); }
#else
#define DEBUGSTR(msg...)        { printf("P2: "); printf( msg); }
#endif
#else
#define DEBUGSTR(msg...)    ((void) 0)
#endif

Таким образом, я могу сказать в моей консоли, какая программа дает сообщение об ошибке... также я могу легко искать сообщения об ошибках...

Лично мне не нравится #defining только часть выражения...

Ответ 10

Это было сделано. Я не рекомендую. Нет времени на тестирование, но механизм выглядит примерно так:

 #define printd_CAT(x) x ## x
 #ifndef DEBUG
    #define printd printd_CAT(/)
 #else
    #define printd printf
 #endif

Это работает, если ваш компилятор обрабатывает//комментарии в самом компиляторе (нет гарантии, как ANSI, гарантировать, что есть два прохода для /* комментариев).