115

I am using Visual Studio 2010. I have read that in C++ it is better to use <cmath> rather than <math.h>.

But in the program I am trying to write (Win32 console application, empty project) if I write:

#define _USE_MATH_DEFINES
#include <math.h>

it compiles, while if I write

#define _USE_MATH_DEFINES
#include <cmath>

it fails with

error C2065: 'M_PI' : undeclared identifier

Is it normal? Does it matter if I use cmath or math.h? If yes, how can I make it work with cmath?

UPDATE: if I define _USE_MATH_DEFINES in the GUI, it works. Any clue why this is happening?

hyperknot
  • 13,454
  • 24
  • 98
  • 153

7 Answers7

141

Interestingly I checked this on an app of mine and I got the same error.

I spent a while checking through headers to see if there was anything undef'ing the _USE_MATH_DEFINES and found nothing.

So I moved the

#define _USE_MATH_DEFINES
#include <cmath>

to be the first thing in my file (I don't use PCHs so if you are you will have to have it after the #include "stdafx.h") and suddenly it compile perfectly.

Try moving it higher up the page. Totally unsure as to why this would cause issues though.

Edit: Figured it out. The #include <math.h> occurs within cmath's header guards. This means that something higher up the list of #includes is including cmath without the #define specified. math.h is specifically designed so that you can include it again with that define now changed to add M_PI etc. This is NOT the case with cmath. So you need to make sure you #define _USE_MATH_DEFINES before you include anything else. Hope that clears it up for you :)

Failing that just include math.h you are using non-standard C/C++ as already pointed out :)

Edit 2: Or as David points out in the comments just make yourself a constant that defines the value and you have something more portable anyway :)

αλεχολυτ
  • 4,792
  • 1
  • 35
  • 71
Goz
  • 61,365
  • 24
  • 124
  • 204
  • Having defined it before `stdafx.h` is the OPs problem I have faced this behavior before. – Alok Save Jul 03 '11 at 16:00
  • @Als: Nah its not that ... have cracked it and explained in my edit above :) – Goz Jul 03 '11 at 16:04
  • Well that was the first thing to do, keep it above all other heasders I asked the OP to do the same....Anyhow will delete my answer since your answer says the actual reason of why it should be before standard headers. – Alok Save Jul 03 '11 at 16:06
  • 3
    You would get this behavior, for example, if something else happened to #include before you do. That said, there is nothing in the standard that says has to include , or that it has to enable the non-standard definitions in . Unfortunately, M_PI is non-standard. For portability, the best thing to do is define it yourself. Better yet, make it a `const static double` rather than a #defined value. – David Hammen Jul 03 '11 at 16:06
  • @Als: But hes screwed if cmath is included from one of the #includes called from the pch ... – Goz Jul 03 '11 at 16:07
  • 1
    @David Hammen: Agreed .. defining it yourself is definitely the most portable option :) – Goz Jul 03 '11 at 16:08
  • Yes, please move the #define _USE_MATH_DEFINES #include to be the first thing in your source file (without using PCHs ) .and suddenly it compile perfectly. – bruce Oct 03 '16 at 08:36
  • When using PCHs, make #define _USE_MATH_DEFINES the first line in the StdAfx.h file. Even better, define it as a compiler flag /D_USE_MATH_DEFINES. – Jeffrey Faust Sep 19 '19 at 14:32
  • I have huge trouble in getting this to work. For some reason MS2019 highlights ```M_PI``` as if it recognizes it and it even indicates the value when hovering above it. But still when I compile it says undeclared identifyer. – ManyQuestions Apr 09 '21 at 11:44
19

Consider adding the switch /D_USE_MATH_DEFINES to your compilation command line, or to define the macro in the project settings. This will drag the symbol to all reachable dark corners of include and source files leaving your source clean for multiple platforms. If you set it globally for the whole project, you will not forget it later in a new file(s).

Thinkeye
  • 655
  • 6
  • 6
  • It's probably a good answer when operating from VisualStudio, but note that it did not solve the problem for me when compiling thru the Matlab mex command line (I used `mex -D_USE_MATH_DEFINES`). Only adding `/Y-` smewhere in some Matlab mexoptions file helped... – aka.nice Oct 16 '19 at 16:46
12

This works for me:

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

using namespace std;

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

    return 0;
}

Compiles and prints pi like is should: cl /O2 main.cpp /link /out:test.exe.

There must be a mismatch in the code you have posted and the one you're trying to compile.

Be sure there are no precompiled headers being pulled in before your #define.

rubenvb
  • 74,642
  • 33
  • 187
  • 332
  • What version of VisualStudio are you using? – Goz Jul 03 '11 at 15:54
  • The same program worked fine for me using Visual C++ 2010 Express Edition's command line compiler. The only difference is that I used std::printf() from instead of std::cout from . –  Jul 03 '11 at 16:00
  • 5
    Yeah I figured it out ... its because maths.h is called from within cmath's header guards ... so maths.h has already been included from an earlier header without the #define set :) – Goz Jul 03 '11 at 16:06
7

With CMake it would just be

add_compile_definitions(_USE_MATH_DEFINES)

in CMakeLists.txt.

FLUXparticle
  • 733
  • 6
  • 16
6

This is still an issue in VS Community 2015 and 2017 when building either console or windows apps. If the project is created with precompiled headers, the precompiled headers are apparently loaded before any of the #includes, so even if the #define _USE_MATH_DEFINES is the first line, it won't compile. #including math.h instead of cmath does not make a difference.

The only solutions I can find are either to start from an empty project (for simple console or embedded system apps) or to add /Y- to the command line arguments, which turns off the loading of precompiled headers.

For information on disabling precompiled headers, see for example https://msdn.microsoft.com/en-us/library/1hy7a92h.aspx

It would be nice if MS would change/fix this. I teach introductory programming courses at a large university, and explaining this to newbies never sinks in until they've made the mistake and struggled with it for an afternoon or so.

user3533658
  • 189
  • 2
  • 2
  • i confirm that hacking /Y- worked for me, for C code #include – aka.nice Oct 16 '19 at 16:34
  • 1
    This is not an issue in VS at all. `_USE_MATH_DEFINES` should be defined prior to including any headers. Typically either through project setting or through configuration header. It is wrong to assume that simply putting it at the first line will cause it to be defined prior to all headers. – user7860670 Apr 01 '20 at 16:42
2

As suggested by user7860670, right-click on the project, select properties, navigate to C/C++ -> Preprocessor and add _USE_MATH_DEFINES to the Preprocessor Definitions.

That's what worked for me.

Den-Jason
  • 2,395
  • 1
  • 22
  • 17
1

According to Microsoft documentation about Math Constants:

The file ATLComTime.h includes math.h when your project is built in Release mode. If you use one or more of the math constants in a project that also includes ATLComTime.h, you must define _USE_MATH_DEFINES before you include ATLComTime.h.

File ATLComTime.h may be included indirectly in your project. In my case one possible order of including was the following:

project's "stdafx.h"<afxdtctl.h><afxdisp.h><ATLComTime.h><math.h>

αλεχολυτ
  • 4,792
  • 1
  • 35
  • 71
  • This may explain why /Y- (disable stdafx.h) would solve the problem, however it remains to explain why providing `-D_USE_MATH_DEFINES` in the default compiler settings does not suffice to solve the problem... Since compilation was via Matlab mex command for my own problem, it's not that obvious to track... – aka.nice Oct 16 '19 at 16:41