2

这个问题与以下任何一个都不相同:

我正在运行 Windows 7 和 Visual Studio Express 2012,但我希望两者都不会影响这个问题的答案。

tl;dr 我将如何最恰当地抵消/防止/容忍 math.h 中以下摘录的影响,同时仍允许使用 Visual C++ 进行编译?

#if     !__STDC__

/* Non-ANSI names for compatibility */

#define DOMAIN      _DOMAIN
#define SING        _SING
#define OVERFLOW    _OVERFLOW
#define UNDERFLOW   _UNDERFLOW
#define TLOSS       _TLOSS
#define PLOSS       _PLOSS

#define matherr     _matherr

背景:我正在编写一个业余爱好的基于文本的 C++ 项目,其总体目标远远超出了这个问题的范围。我正在使用 GNU Make(为了熟悉和可移植性)用 Cygwin g++ 和 cl.exe 编译它,并假设一个严格符合标准的环境......到目前为止。我开始认为 Windows 根本不允许这样的假设。

我有一个枚举,其成员包括OVERFLOWand UNDERFLOW。下面描述的问题可能会迫使我更改这些名称,但我更愿意保留它们,因为它们最适合我的目的,尽管有 Windows 头文件等外部影响。

GCC、Visual C++ 和 Mac OS X 的头文件(独立于 llvm-gcc)都默认在 math.h 中定义OVERFLOWUNDERFLOW以及其他非标准宏。

  • GCC 有一系列有据可查的方法来彻底阻止这些定义。
  • Mac OS X 有几个未记录的方法可以做到这一点,其中一个 ( _POSIX_C_SOURCE) 与 GCC 的文档一致。(我提到这一点是为了补偿 Apple 缺乏文档;我有这些标识符的历史。)
  • MSDN将 /u 命令行选项记录为一种(通过__STDC__宏)防止在 Visual C++ 中定义一些 非标准宏的方法。如本问题开头所示,__STDC__阻止定义OVERFLOWand UNDERFLOW

在发现 /u 开关会阻止我关心的定义后,我将它添加到我的 makefile 中。但后来我从 crtdefs.h 的第 44 行收到了一个新错误:

error C1189: Only Win32 target supported!

这是因为_WIN32不再定义。一点搜索表明 crtdefs.h 与 Windows 驱动程序开发工具包有关。我不是在开发驱动程序;我可以以某种方式不使用该标题吗?还是我只需要重命名我的枚举成员以容忍非标准的 Windows 行为?

4

3 回答 3

1

脑海中浮现出两种可能性。

首先是确保在包含 时反转特定效果math.h,例如:

#include <math.h>
#undef OVERFLOW
#undef UNDERFLOW

现在,这也可能导致某些地方的代码出现问题,这些代码期望这些东西被正确定义。但是,即使在这种情况下,您也可以修改您的软件以使用不同的名称math.h

#include <math.h>
#undef OVERFLOW
#undef UNDERFLOW
#define MATH_H_OVERFLOW  _OVERFLOW
#define MATH_H_UNDERFLOW _UNDERFLOW

您只需要确保所有想要使用源代码(如库之类的已编译代码)都math.h使用常量MATH_H_*而不是枚举中的常量。


第二个是仔细考虑你在这个任务中付出的努力,而不是简单地将你的enum成员重命名为冲突的东西所需要的努力。像使用Overflow枚举(而不是OVERFLOW)这样的东西将是我的第一次尝试,因为两者中的信息量仍然完全相同,并且它消除了直接的冲突。

是的,我知道找到一种不涉及这种情况的方法会很好,但是您应该从事交付软件的业务,而不是花费过多的时间来解决与您的环境有关的小问题 :-)

于 2012-09-18T02:32:14.073 回答
1

而不是使用/u具有多种效果的编译器开关,只需使用/D__STDC__=1导致__STDC__宏被定义的,而不是别的。

于 2012-09-18T04:15:40.097 回答
0

在 C++11 中,您可以使用作用域枚举:

enum class Flows { Underflow, Overflow };

您现在参考 Flows::Underflow 和 Flows::Overflow。

即使在 C++98 中,使用类进行模拟也是一种很好的做法:

class Flows
{
public:
    enum Value { Underflow, Overflow };
};
于 2012-09-18T03:24:37.403 回答