2009-11-23 2 views
19

Я пытаюсь сделать отладочную систему, но, похоже, она не работает.Можете ли вы #define комментарий в C?

То, что я хотел сделать что-то вроде этого:

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

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

if (DEBUG) 
    printf(...) 

code 

if (DEBUG) 
    printf(...) 

... 
+1

Прямой дубликат http://stackoverflow.com/questions/1644868/c-define-macro-for-debug-printing/1644898#1644898 и, возможно, и другие. –

+0

@JonathanLeffler * use case * (создание макроса печати только для отладки) является дубликатом http://stackoverflow.com/questions/1644868/c-define-macro-for-debug-printing/1644898#1644898, но литальный вопрос, заданный (могу ли я включить '//' в '# define'), не является, и вопрос, заданный буквально, интересен и полезен другим. Наложение неудачно, но здесь есть особый вопрос, который имеет значение; он не должен быть закрыт. –

+0

@MarkAmery: название - это проблема [XY Problem] (http://www.perlmonks.org/?node_id=542341) - решение, которое пытается выполнить пользователь, находится в номинированном дубликате, но вопрос просят что-то тангенциальное, которое даже не достигнет того, чего они хотят. –

ответ

21

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

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

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

+0

Также проблема '/ * * /' комментариев, которые пытаются охватить несколько файлов с помощью '# include', является проблемой. – chux

7

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

+0

Спасибо, здравомыслие наконец .. кроме его главным образом работы препроцессора. –

+0

В этом случае вы можете просто вызвать вашу функцию printd – tadman

+2

Это не отключает оценку аргументов и не отключает требование о том, чтобы аргументы были действительными (например, объявлены, например). Другими словами, он не выполняет то, что было запрошено. – AnT

2

Стандартный способ заключается в использовании

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

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

16

С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 
+0

Правильно, но не совсем портативно. –

+0

Добавлен переносной путь :) – Xeor

+0

Гораздо лучше, но опять же «портативная» версия не отключает проверки достоверности аргументов. Правильный способ сделать это в реализации, отличной от C99, приведен в ответе Тима. – AnT

0

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

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

void do_nothing() { ; } 

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

17

Общая Хитрость заключается в том, чтобы сделать это:

#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, за которым следует аргумент singl, который на самом деле представляет собой несколько элементов в скобках. Затем скобки интерпретируются как скобки, необходимые в вызове функции printf, поэтому все это работает.

+0

Почему бы не использовать printf (x) в первом макросе? не будет работать? – KeatsPeeks

+1

Хороший вопрос. Теперь объясняется в тексте ответа. – Tim

+0

также вы можете использовать OUTPUT (x ...) printf (x), чтобы избежать double(). –

0

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

#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 только часть выражения ...

0

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

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

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

1

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

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

требует, чтобы определить не только DEBUG, но и придать ему не-ZER0 значение.

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

5

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

#define CMT/##/

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

Смежные вопросы