你可以在C中定义评论吗?

时间:2009-11-23 18:54:23

标签: c debugging c-preprocessor

我正在尝试调试系统,但似乎无法正常工作。

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

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

有办法吗?我有很多调试消息,我不想这样做:

if (DEBUG)
    printf(...)

code

if (DEBUG)
    printf(...)

...

12 个答案:

答案 0 :(得分:28)

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

此外,任何以后通过使用任何宏技巧“形成”评论的尝试都不能保证有效。编译器不需要将“迟到的”注释识别为注释。

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

答案 1 :(得分:20)

常见的诀窍是:

#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函数调用中所需的括号,因此一切正常。

答案 2 :(得分:18)

С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

答案 3 :(得分:8)

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

答案 4 :(得分:5)

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

#define CMT / ## /

但并非所有编译器的受赠人。

答案 5 :(得分:2)

标准方法是使用

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

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

答案 6 :(得分:1)

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

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

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

附录: 也适用于std::cout

答案 7 :(得分:1)

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

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

然后你可以做

if constexpr (DEBUG) /* debug code */

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

答案 8 :(得分:0)

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

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

void do_nothing() { ; }

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

答案 9 :(得分: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只是表达的一部分......

答案 10 :(得分:0)

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

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

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

答案 11 :(得分:0)

您可以利用if的优势。例如,

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

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