2012-09-18 71 views
1

这个问题是不一样的任一:严格的标准,符合的Visual C++

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

我有一个枚举,其成员包括OVERFLOWUNDERFLOW。下面描述的问题有可能迫使我改变这些名字,但我宁愿保留它们,因为它们最适合我的目的,尽管有诸如Windows头文件之类的外部影响。

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

  • GCC有a selection干净地防止这些定义的记录手段。
  • Mac OS X有几个无证的方法可以做到这一点,其中一个(_POSIX_C_SOURCE)与GCC的文档一致。 (我提到这是为了补偿苹果缺乏文档的兴趣;我有这些标识符的历史记录)
  • MSDN documents/u命令行选项作为一种手段(通过__STDC__宏)阻止定义a fewnon-standard macros in Visual C++。如问题开头所示,__STDC__阻止定义OVERFLOWUNDERFLOW

一旦发现/ u开关会阻止我所关心的定义,我将它添加到我的生成文件中。但后来我得到了一个新的错误从线44的crtdefs.h:

error C1189: Only Win32 target supported! 

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

+0

我听到了吗 - C++/CLI?与在公共语言基础结构中一样,AKA .NET?放弃对标准合规性的追求。 CLI和微软的扩展一样多。 –

+1

@Seva CLI =命令行界面 – Grault

回答

1

代替使用/u编译器开关,它具有multiple effects的,只是使用/D__STDC__=1这导致要定义的__STDC__宏没有别的。

+0

><我应该想到这一点。我不自觉地将该页面解释为表明它们是有效的同义词。这解决了问题;非常感谢。 – Grault

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)将是我的第一次尝试,因为两者中的信息量仍然完全相同,并消除了当前的冲突。

是的,我知道这将是不错找到一种方式,不涉及这一点,但你应该在提供软件,而不是花时间过多数量的工作与你的周围环境的未成年人挑剔的业务: - )

+0

关于#1,我忘了提及我担心这不是很干净......我更喜欢防止而不是尽可能抵消。但是,除非我遇到不这样做的原因,否则我可能会这样做。 (我从来没有使用math.h宏。) – Grault

+0

并重新:#2 ...是的,但我很固执,这是供将来参考。我想我以后会遇到这种事情,所以我现在可以处理它。 – Grault

+0

@Jesdisciple,#1 _实际上会阻止它,只是因为标准决定了预处理器阶段发生在“正确”编译(包括创建枚举)之前。在定义枚举或_use_这些符号时,它们不会以'#define'值存在。如果您有一些源代码依赖于math.h值,但这可以通过使用'MATH_H_ *'常量或者重命名枚举字段来解决,这不会有帮助。 – paxdiablo

0

在C++ 11可以使用范围的枚举:

enum class Flows { Underflow, Overflow }; 

现在是指流动::下溢和流程::溢出。

即使在C++ 98它的良好的实践中使用的与类模拟此:

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

我将它们放在一个名称空间中;预处理器不关心并将值3和4放在标识符所在的位置。 – Grault

+0

+1/@Jesdisciple:你在这里错过了一个关键点......此解决方案使用混合大小写标识符,而不是大写。除了通常用于模板参数的单大写字符和单字符+数字标识符外,全部大写标识符应留给预处理器宏。你应该使用混合大小写或小写 - 微妙的优点和缺点,但要么会防止冲突。 –

+0

@TonyDelroy我想我受到其他语言的污染;我将全部大写与常量的语义联系在一起,粗略地说,它们都是由宏和编译时常量(如枚举成员)来满足的。我通常还会憎恨宏(类型不安全,基本上是单独语言的一部分),并且宁愿从我的环境中删除尽可能多的非标准宏,即使除了这个问题之外。 – Grault