1

我知道“便携式”和“宏”这两个词通常不会一起出现,但我的代码通常充满了#ifdef _DEBUG确认预期结果的标签(我使用 VS2012)。我想让我的代码可移植到 Unix 系统。

根据这篇文章,我的理解是 Visual Studio 使用_DEBUG和 C 标准使用NDEBUG,但它们的功能不同(_DEBUG标志调试模式,NDEBUG标志断言)。

如果我希望我的代码尽可能可移植,#ifndef NDEBUG如果我只希望这些代码行在断言处于活动状态时运行,我应该使用吗?这在 Visual Studio 中会产生什么后果?它似乎有效,但我想确保我没有遗漏任何东西;IE。_DEBUG当有一个非常好的 C 标准替代品时,为什么微软会使用呢?历史原因?

4

4 回答 4

3

那艘船很久以前航行,MSVC 答应了,因为抵抗是徒劳的。这如您所料:

#ifdef NDEBUG
#pragma message("Release build selected")
#endif

那个宏不会像有些人那样完全从天上掉下来。项目 + 属性、C/C++、预处理器、预处理器定义设置。它的工作原理不是因为编译器加入了 Borg,而是 IDE 加入了。或者更具体一点,项目模板就是这样做的。一个很好的借口:)

所以不,使宏可移植完全不是问题。只需要让你的makefile正确。

于 2013-09-15T22:55:08.403 回答
2

我不知道 MS 不使用 NDEBUG 宏而是定义 _DEBUG 的真正原因。我的猜测是它与_ASSERT而不是的定义有关assert

问题assert()在于 C 标准定义要求它向控制台和abort程序打印一行。但是Windows程序通常没有控制台,所以MS认为弹出一个窗口会很好。但是assert()弹出一个窗口不符合标准,因此开发了一个类似但不同的宏:_ASSERT,以及一个不同的宏来控制其行为:_DEBUG

_UNICODE和宏也存在类似的混乱UNICODE,但这是另一个故事......

请注意,在 Visual C++ 项目的默认配置中,定义了调试模式_DEBUG,但NDEBUG没有定义。虽然在发布模式下_DEBUG未定义,但NDEBUG已定义。因此,对于您自己的代码,您可以使用其中任何一种。但是很自然,如果你想要可移植,你应该使用NDEBUG,因为这个_DEBUG名字是保留给编译器实现的。

于 2013-09-15T22:52:14.770 回答
1

尽管有点做作,但您可以这样做以使其具有便携性

#if defined(__unix__) && defined(NDEBUG)
#define _DEBUG
#endif
于 2013-09-15T22:49:45.643 回答
1

据我所知,唯一(按标准)NDEBUG应该影响的是assert宏。因此,如果想要添加他们的调试工具,他会添加自己的宏定义,例如_DEBUG(不影响或依赖NDEBUG)。

为了使您的调试代码可移植,您最好为相同的目的定义自己的宏。

然后作为一个选项,您可以打开和关闭它,例如,取决于NDEBUG存在。

于 2013-09-15T22:57:59.607 回答