M_PI适用于math.h,但不适用于Visual Studio中的cmath

hyp*_*not 85 c++ visual-studio-2010 visual-studio

我正在使用Visual Studio 2010.我已经读过,在C++中,最好使用<cmath>而不是<math.h>.

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

#define _USE_MATH_DEFINES
#include <math.h>
Run Code Online (Sandbox Code Playgroud)

如果我写的话,它会编译

#define _USE_MATH_DEFINES
#include <cmath>
Run Code Online (Sandbox Code Playgroud)

它失败了

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

这是正常的吗?如果我使用cmath或math.h是否重要?如果是,我怎样才能使用cmath?

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

Goz*_*Goz 105

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

我花了一些时间检查标题,看看是否有任何东西未找到_USE_MATH_DEFINES并且什么也没找到.

所以我感动了

#define _USE_MATH_DEFINES
#include <cmath>
Run Code Online (Sandbox Code Playgroud)

成为我文件中的第一件事(我不使用PCHs,所以如果你是你必须在#include"stdafx.h"之后得到它)并且突然它完全编译.

尝试将其向上移动到页面上方.完全不确定为什么这会导致问题.

编辑:想出来.#include发生在cmath的标题保护中.这意味着#includes列表中较高的位置包括未指定#define的cmath.math.h是专门设计的,所以你可以再次包含它,现在更改为添加M_PI等.这不是cmath的情况.因此,在包含其他内容之前,您需要确保#define _USE_MATH_DEFINES.希望能为你清除它:)

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

编辑2:或者正如大卫在评论中指出的那样只是让自己成为一个定义值的常量,而且你还有更多可移植的东西:)

  • 例如,如果在执行之前发生了#include <math.h>的其他事情,您会得到此行为.也就是说,标准中没有任何内容表示<cmath>必须包含<math.h>,或者必须在<math.h>中启用非标准定义.不幸的是,M_PI是非标准的.为了便于携带,最好的办法是自己定义.更好的是,使它成为`const static double`而不是#defined值. (3认同)

Thi*_*eye 13

考虑将开关/ D_USE_MATH_DEFINES添加到编译命令行,或在项目设置中定义宏.这会将符号拖动到包含源文件和源文件的所有可到达黑暗角落,从而使源清理多个平台.如果您为整个项目全局设置它,您将不会在以后的新文件中忘记它.


rub*_*nvb 8

这对我有用:

#define _USE_MATH_DEFINES
#include <cmath>
#include <iostream>

using namespace std;

int main()
{
    cout << M_PI << endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译和打印pi应该是:cl /O2 main.cpp /link /out:test.exe.

您发布的代码与您尝试编译的代码之间必定存在不匹配.

确保在您之前没有预先编译好的标题#define.

  • 是的,我想通了......因为maths.h是从cmath的标题守卫中调用的......所以maths.h已经包含在没有#define设置的早期标题中:) (4认同)

FLU*_*cle 7

使用 CMake 就可以了

add_compile_definitions(_USE_MATH_DEFINES)
Run Code Online (Sandbox Code Playgroud)

CMakeLists.txt


小智 5

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

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

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

如果MS可以更改/修复此问题,那就太好了。我在一所大型大学教授入门编程课程,并向新手解释这一点,直到他们犯了错误并在一个下午左右的时间里为之苦苦挣扎。