Можете ли вы #define комментарий в C?
Я пытаюсь сделать отладочную систему, но, похоже, она не работает.
То, что я хотел выполнить, это примерно так:
#ifndef DEBUG
#define printd //
#else
#define printd printf
#endif
Есть ли способ сделать это? У меня много сообщений об отладке, и мне не понравится:
if (DEBUG)
printf(...)
code
if (DEBUG)
printf(...)
...
Ответы
Ответ 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, гарантировать, что есть два прохода для /* комментариев).