一、问题根源
在 Linux / GCC / Clang 中:
#include<cmath>通常就能用:
M_PI但在MSVC中:
M_PI默认不定义- 需要显式开启宏,或自己定义
- 或使用C++20 标准方案
所以才会出现:
error C2065: “M_PI”: 未声明的标识符二、最简单粗暴(不推荐,但常见)
在使用前手动定义:
#ifndefM_PI#defineM_PI3.14159265358979323846#endif能用
不优雅
易重复定义
不类型安全
三、MSVC 官方方式(老项目常用)
1.在#include <cmath>之前:
#define_USE_MATH_DEFINES#include<cmath>然后就可以:
doublex=M_PI;注意:
- 必须在
<cmath>之前 - 只对 MSVC 有意义
- 属于“平台特性”
稳定
兼容老代码
非标准 C++
四、 推荐方案
使用C++20std::numbers::pi
#include<numbers>doublex=std::numbers::pi;或指定类型:
doublex=std::numbers::pi_v<double>;floaty=std::numbers::pi_v<float>;标准
类型安全
无宏
跨平台
不污染命名空间
强烈推荐
五、如果在模板 / 数值库中(非常重要)
不要在模板中用M_PI
template<typenameT>Tfoo(){returnT(M_PI);// 不推荐}推荐:
#include<numbers>template<typenameT>Tpi(){returnstd::numbers::pi_v<T>;}六、Eigen / GTSAM / 数值库中的惯用写法
很多数值库内部都会写:
constexprdoublekPi=3.14159265358979323846;或:
staticconstexprdoublepi=std::acos(-1.0);也可以用:
constexprdoublepi=std::acos(-1);标准
无宏
编译期常量
七、工程级方案(如果不能改源码)
在 CMake 中:
add_definitions(-D_USE_MATH_DEFINES)或:
target_compile_definitions(your_target PRIVATE _USE_MATH_DEFINES)八、最终建议
| 场景 | 推荐 |
|---|---|
| 新项目 / 现代 C++ | std::numbers::pi |
| 旧 MSVC 项目 | _USE_MATH_DEFINES |
| 模板 / 数值库 | std::numbers::pi_v<T> |
| 快速修 bug | 手动#define M_PI(临时) |