【问题标题】:M_PI works with math.h but not with cmath in Visual StudioM_PI 适用于 math.h 但不适用于 Visual Studio 中的 cmath
【发布时间】:2011-09-27 16:10:39
【问题描述】:

我正在使用 Visual Studio 2010。我读过在 C++ 中使用<cmath> 比使用<math.h> 更好。

但是在我尝试编写的程序中(Win32 控制台应用程序,空项目),如果我写的话:

#define _USE_MATH_DEFINES
#include <math.h>

它编译,而如果我写

#define _USE_MATH_DEFINES
#include <cmath>

它失败了

错误 C2065:“M_PI”:未声明的标识符

正常吗?我使用 cmath 还是 math.h 有关系吗?如果是,我怎样才能使它与 cmath 一起使用?

更新:如果我在 GUI 中定义 _USE_MATH_DEFINES,它就可以工作。任何线索为什么会发生这种情况?

【问题讨论】:

  • 您的源文件是 .c 还是 .cpp?
  • 瑞士:在这里不重要。
  • 非常奇怪......我可以确认我在 VS2010 上遇到了同样的问题......我正在研究是什么阻止了定义通过......它必须在某个地方取消定义......但是我不知道在哪里
  • 使用 x86,它会报错 C2065。使用 x64,则没有错误。

标签: c++ visual-studio visual-studio-2010


【解决方案1】:

使用 CMake 就可以了

add_compile_definitions(_USE_MATH_DEFINES)

在CMakeLists.txt.

【讨论】:

    【解决方案2】:

    按照用户 7860670 的建议,右键单击项目,选择属性,导航到 C/C++ -> Preprocessor 并将 _USE_MATH_DEFINES 添加到 Preprocessor Definitions。

    这对我有用。

    【讨论】:

      【解决方案3】:

      有趣的是,我在我的一个应用程序上检查了这个,我得到了同样的错误。

      我花了一段时间检查标头,看看是否有任何未定义 _USE_MATH_DEFINES 的内容,但一无所获。

      所以我搬了

      #define _USE_MATH_DEFINES
      #include <cmath>
      

      成为我文件中的第一件事(我不使用 PCH,所以如果你是,你必须在 #include "stdafx.h" 之后拥有它)然后它突然完美编译。

      尝试将它移到页面更高的位置。完全不确定为什么这会导致问题。

      编辑:想通了。 #include &lt;math.h&gt; 出现在 cmath 的标头保护中。这意味着#includes 列表中更高的内容包括cmath 而没有指定#define。 math.h 是专门设计的,因此您可以再次包含它,该定义现在更改为添加 M_PI 等。cmath 不是这种情况。因此,在包含其他任何内容之前,您需要确保您 #define _USE_MATH_DEFINES。希望能为您解决问题:)

      如果只包含 math.h 失败,您正在使用非标准 C/C++,正如已经指出的 :)

      编辑 2:或者正如 David 在 cmets 中指出的那样,只要让自己成为一个定义值的常量,无论如何你就有了更便携的东西 :)

      【讨论】:

      • 在stdafx.h 之前定义它是我之前遇到过这种行为的 OPs 问题。
      • @Als:不,它不是那个......已经破解它并在我上面的编辑中解释了:)
      • 嗯,这是要做的第一件事,把它放在所有其他标题之上应该在标准标题之前。
      • 你会得到这种行为,例如,如果在你这样做之前#include 发生了其他事情。也就是说,标准中没有规定 必须包含 ,或者它必须启用 中的非标准定义。不幸的是,M_PI 是非标准的。对于可移植性,最好的办法是自己定义。更好的是,将其设为 const static double 而不是 #defined 值。
      • @David Hammen:同意.. 自己定义绝对是最便携的选择 :)
      【解决方案4】:

      根据微软关于Math Constants的文档:

      当您的项目以发布模式构建时,文件ATLComTime.h 包括math.h。如果您在还包含ATLComTime.h 的项目中使用一个或多个数学常量,则必须在包含ATLComTime.h 之前定义_USE_MATH_DEFINES。

      文件ATLComTime.h 可能会间接包含在您的项目中。就我而言,一种可能的包含顺序如下:

      项目的"stdafx.h" → &lt;afxdtctl.h&gt; → &lt;afxdisp.h&gt; → &lt;ATLComTime.h&gt; → &lt;math.h&gt;

      【讨论】:

      • 这可以解释为什么 /Y- (disable stdafx.h) 会解决问题,但是仍然需要解释为什么在默认编译器设置中提供-D_USE_MATH_DEFINES 不足以解决问题。 . 由于我自己的问题是通过 Matlab mex 命令编译的,所以跟踪起来并不那么明显......
      【解决方案5】:

      在构建控制台或 Windows 应用程序时,这仍然是 VS Community 2015 和 2017 中的一个问题。 如果项目是使用预编译的头文件创建的,那么预编译的头文件显然是在任何#includes 之前加载的,因此即使#define _USE_MATH_DEFINES 是第一行,它也不会编译。 #include math.h 而不是 cmath 并没有什么不同。

      我能找到的唯一解决方案是从一个空项目(对于简单的控制台或嵌入式系统应用程序)开始,或者将 /Y- 添加到命令行参数,这会关闭预编译头文件的加载。

      有关禁用预编译标头的信息,请参见示例 https://msdn.microsoft.com/en-us/library/1hy7a92h.aspx

      如果 MS 能改变/解决这个问题就好了。我在一所大型大学教授入门编程课程,向新手解释这一点永远不会沉没,直到他们犯了错误并为此苦苦挣扎了一个下午左右。

      【讨论】:

      • 我确认 hacking /Y- 对我有用,对于 C 代码#include
      • 这在 VS 中根本不是问题。 _USE_MATH_DEFINES 应在包含任何标题之前定义。通常通过项目设置或配置标题。假设简单地将其放在第一行会导致在所有标题之前定义它是错误的。
      【解决方案6】:

      考虑将开关 /D_US​​E_MATH_DEFINES 添加到编译命令行,或在项目设置中定义宏。这会将符号拖到包含文件和源文件的所有可到达的暗角,使您的源代码干净,适用于多个平台。如果您为整个项目全局设置它,您以后不会在新文件中忘记它。

      【讨论】:

      • 从 VisualStudio 操作时这可能是一个很好的答案,但请注意,在通过 Matlab mex 命令行编译时它并没有解决我的问题(我使用了mex -D_USE_MATH_DEFINES)。仅在某些 Matlab mexoptions 文件中添加 /Y- smewhere 有助于...
      【解决方案7】:

      这对我有用:

      #define _USE_MATH_DEFINES
      #include <cmath>
      #include <iostream>
      
      using namespace std;
      
      int main()
      {
          cout << M_PI << endl;
      
          return 0;
      }
      

      编译并打印pi,就像应该:cl /O2 main.cpp /link /out:test.exe。

      您发布的代码与您尝试编译的代码一定不匹配。

      确保在您的 #define 之前没有拉入任何预编译的标头。

      【讨论】:

      • 您使用的是什么版本的 VisualStudio?
      • 使用 Visual C++ 2010 Express Edition 的命令行编译器,相同的程序对我来说运行良好。唯一的区别是我使用了来自 的 std::printf() 而不是来自 . 的 std::cout
      • 是的,我想通了……因为 maths.h 是从 cmath 的标头保护中调用的……所以 maths.h 已经包含在没有#define 集的早期标头中:)
      猜你喜欢
      • 2013-04-30
      • 1970-01-01
      • 2021-02-25
      • 2020-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-23
      • 1970-01-01
      相关资源
      最近更新 更多