你可以#define在C中发表评论吗?

我正在尝试做一个调试系统,但它似乎无法工作。

我想要完成的是这样的事情:

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

有没有办法做到这一点? 我有很多调试消息,我不想这样做:

 if (DEBUG) printf(...) code if (DEBUG) printf(...) ... 

不,你不能。 在开始处理任何预处理指令之前,将从代码中删除注释。 因此,您无法在宏中添加注释。

此外,任何尝试通过使用任何宏诡计随后“形成”评论的尝试都不能保证起作用。 编译器不需要将“迟到”注释识别为注释。

实现所需内容的最佳方法是在C99中使用带有变量参数的宏(或者,可能使用编译器扩展)。

一个常见的技巧是这样做:

 #ifdef DEBUG #define OUTPUT(x) printf x #else #define OUTPUT(x) #endif #include  int main(void) { OUTPUT(("%s line %i\n", __FILE__, __LINE__)); return 0; } 

这样你就可以获得printf()的全部function,但你必须忍受双括号才能使宏工作。

双括号的要点是:你需要一个集来表示它是一个宏调用,但你不能在C89中的宏中有一个不确定数量的参数。 但是,通过将参数放在它们自己的括号中,它们被解释为单个参数。 当定义DEBUG时扩展宏时,替换文本是单词printf后跟singl参数,实际上是括号中的几个项目。 然后括号被解释为printf函数调用中所需的括号,因此一切正常。

С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 

您可以将所有调试调用放在一个函数中,让它调用printf_debug并将DEBUG放在此函数中。 编译器将优化空函数。

在一些编译器(包括MS VS2010)上,这将起作用,

 #define CMT / ## / 

但没有所有编译器的受助者。

标准方法是使用

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

这样,当您在末尾添加分号时,它会执行您想要的操作。 由于没有操作,编译器将编译出“do … while”

未经测试:编辑:测试,现在自己使用它:)

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

要求您不仅要定义DEBUG ,还要给它一个非零值。

附录:也适用于std::cout

在C ++ 17中,我喜欢使用constexpr来做这样的事情

 #ifndef NDEBUG constexpr bool DEBUG = true; #else constexpr bool DEBUG = false; #endif 

那你可以做

 if constexpr (DEBUG) /* debug code */ 

需要注意的是,与预处理器宏不同,您的范围有限。 您既不能在一个可从另一个调用条件中访问的调试条件中声明变量,也不能在外部函数范围内使用它们。

正如McKay所指出的,如果你只是尝试用//替换printd ,你会遇到问题。 相反,您可以使用variadric宏将printd替换为不执行任何操作的函数,如下所示。

 #ifndef DEBUG #define printd(...) do_nothing() #else #define printd(...) printf(__VA_ARGS__) #endif void do_nothing() { ; } 

使用像GDB这样的调试器也可能有所帮助,但有时快速的printf就足够了。

我经常使用这个构造:

 #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只是表达的一部分……

它已经完成了。 我不推荐它。 没时间测试,但机制有点像这样:

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

如果您的编译器在编译器本身处理//注释(这不保证像ANSI保证有两个/ *注释的传递),这是有效的。

你可以利用if 。 例如,

 #ifdef debug #define printd printf #else #define printd if (false) printf #endif 

如果您设置像-O2这样的优化标志,编译器将删除这些无法访问的代码。 这个方法对std::cout也很有用。