我正在尝试调试系统,但似乎无法正常工作。
我想要完成的是这样的事情:
#ifndef DEBUG
#define printd //
#else
#define printd printf
#endif
有办法吗?我有很多调试消息,我不想这样做:
if (DEBUG)
printf(...)
code
if (DEBUG)
printf(...)
...
答案 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
也有用。