严格遵守Visual C++标准

Strict standards-compliance with Visual C++

本文关键字:标准 C++ Visual 严格遵守      更新时间:2023-10-16

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

  • 将Visual C++Studio/Express设置为严格的ANSI模式
  • 当使用Microsoft';的Visual C++编译器

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

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

#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根本不允许这样的假设。

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

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

  • GCC有一系列文件化的方法,可以干净地防止这些定义
  • MacOSX有几种未记录的方法可以做到这一点,其中一种(_POSIX_C_SOURCE)与GCC的文档一致。(我提到这一点是为了弥补苹果公司缺乏文档的缺陷;我有使用这些标识符的历史。)
  • MSDN记录了/u命令行选项,作为一种防止在Visual C++中定义一些非标准宏的方法(通过__STDC__宏)。如本问题开头所示,__STDC__阻止定义OVERFLOWUNDERFLOW

当发现/u开关会阻止我所关心的定义时,我将其添加到我的makefile中。但后来我从crtdfs的第44行得到了一个新的错误。h:

error C1189: Only Win32 target supported!

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

不要使用具有多种效果的/u编译器开关,只需使用/D__STDC__=1即可定义__STDC__宏,而不使用其他功能。

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

第一个是确保在包含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)进行枚举,因为两者中的信息量仍然完全相同,而且它消除了直接的冲突。

是的,我知道找到一种不涉及这一点的方法是很好的,但你应该从事交付软件的业务,而不是花太多时间处理环境中的小问题:-)

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

enum class Flows { Underflow, Overflow };

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

即使在C++98中,也可以使用类来模拟它:

class Flows
{
public:
enum Value { Underflow, Overflow };
};