M_PIはmath.hで機能しますが、Visual Studioのcmathでは機能しません


94

私は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ですか?
スイス、

1
スイス:ここでは関係ありません。
rubenvb

非常に奇妙です... VS2010でも同じ問題が発生することを確認できます...定義の通過を停止している原因を調べています...どこかで未定義になっているはずです...しかし、どこにあるのかわかりません
ゴズ

x86では、エラーC2065が表示されます。x64では、エラーは発生しません。
user2616989

回答:


116

興味深いことに、私のアプリでこれを確認したところ、同じエラーが発生しました。

ヘッダーを調べて、undef _USE_MATH_DEFINESされていないものがないか確認しましたが、何も見つかりませんでした。

だから私は移動しました

#define _USE_MATH_DEFINES
#include <cmath>

私のファイルの最初のものになるように(私はPCHを使用しないので、もしそうなら、あなたはそれの後にそれを持っている必要があります#include "stdafx.h")そして突然それは完全にコンパイルされます。

ページを上に移動してみてください。なぜこれが問題を引き起こすのかについては全くわかりません。

編集:それを考え出した。#include <math.h>cmathのヘッダーガード内で発生します。これは、#includesのリストの上位にあるものcmath#define指定なしで含まれていることを意味します。 これはmath.h、定義を追加M_PIなどに変更して、再度含めることができるように特別に設計されています。これは、には当てはまりませんcmath。したがって#define _USE_MATH_DEFINES、他のものを含める前に確認する必要があります。それがあなたのためにそれを片付けることを願っています:)

含まれmath.hているだけで失敗すると、すでに指摘したように非標準のC / C ++を使用しています:)

編集2:または、Davidがコメントで指摘しているように、値を定義する定数を作成するだけで、とにかく移植性の高いものになります:)


以前にそれを定義したことstdafx.hが、私が以前にこの動作に直面したOPの問題です。
Alok Save

@Als:いや、それは...それをクラックして、上記の私の編集で説明しました:)
Goz

まあそれは最初にすることでした、私が同じことをするようにOPに依頼した他のすべての見出しより上に置いてください...あなたの答えはそれが標準ヘッダーの前にあるべき実際の理由を述べているので、とにかく私の答えを削除します。
Alok Save

3
たとえば、#include <math.h>を実行する前に何かが起こった場合、この動作が発生します。とはいえ、<cmath>が<math.h>をインクルードしなければならない、または<math.h>の非標準の定義を有効にする必要があると言っている標準には何もありません。残念ながら、M_PIは非標準です。移植性については、自分で定義することをお勧めします。さらに良いのは、それをconst static double#defined値ではなく#にすることです。
David Hammen、2011

1
@David Hammen:同意する..自分で定義するのは間違いなく最も移植性の高いオプションです:)
Goz

14

/ D_USE_MATH_DEFINESスイッチをコンパイルコマンドラインに追加するか、プロジェクト設定でマクロを定義することを検討してください。これにより、インクルードファイルとソースファイルの到達可能なすべての暗いコーナーにシンボルがドラッグされ、ソースが複数のプラットフォームでクリーンになります。プロジェクト全体でグローバルに設定すると、後で新しいファイルで忘れることはありません。


VisualStudioから操作する場合はおそらく良い答えですが、Matlab mexコマンドライン(私はを使用しましたmex -D_USE_MATH_DEFINES)を介してコンパイルするときに問題が解決しなかったことに注意してください。/Y-一部のMatlab mexoptionsファイルのsmewhereを追加するだけで解決しました...
aka.nice

9

これは私にとってはうまくいきます:

#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を使用していますか?
Goz、2011

同じプログラムは、Visual C ++ 2010 Express Editionのコマンドラインコンパイラーを使用してうまく動作しました。唯一の違いは、<iostream>からのstd :: coutではなく、<cstdio>からのstd :: printf()を使用したことです。

4
ええ、私はそれを理解しました...その理由は、maths.hがcmathのヘッダーガード内から呼び出されているためです...したがって、maths.hは、#defineセットなしで以前のヘッダーからすでに含まれています:)
Goz

4

これは、VS Community 2015および2017でコンソールまたはWindowsアプリをビルドする際の問題です。プロジェクトがプリコンパイル済みヘッダーを使用して作成されている場合、プリコンパイル済みヘッダーは#includeのにロードされるため、#define _USE_MATH_DEFINESが最初の行であってもコンパイルされません。cmathの代わりに#math.hを含めても違いはありません。

私が見つけることができる唯一の解決策は、空のプロジェクト(単純なコンソールまたは組み込みシステムアプリの場合)から開始するか、コマンドライン引数に/ Y-を追加して、プリコンパイル済みヘッダーのロードをオフにすることです。

プリコンパイル済みヘッダーを無効にする方法については、たとえば、https: //msdn.microsoft.com/en-us/library/1hy7a92h.aspxを参照して ください。

MSがこれを変更/修正するとよいでしょう。私は大規模な大学でプログラミングの入門コースを教えており、初心者が間違いを犯して午後などに苦労するまで、これを説明することはありません。


ハッキング/ Y-が私のために機能したことを確認します。Cコード#include <math.h>の場合
aka.nice

1
これはVSの問題ではありません。_USE_MATH_DEFINESヘッダーを含める前に定義する必要があります。通常は、プロジェクト設定または構成ヘッダーを使用します。それを最初の行に置くだけですべてのヘッダーの前に定義されると仮定するのは誤りです。
user7860670

1

数学定数に関するマイクロソフトのドキュメントによると:

ファイルATLComTime.hmath.h、プロジェクトがリリースモードでビルドされたときに含まれます。も含むプロジェクトで1つ以上の数学定数をATLComTime.h使用_USE_MATH_DEFINESする場合は、含める前に定義する必要がありますATLComTime.h

ファイルATLComTime.hはプロジェクトに間接的に含まれる場合があります。私の場合、含めることができる1つの順序は次のとおりです。

プロジェクトの"stdafx.h"<afxdtctl.h><afxdisp.h><ATLComTime.h><math.h>


これは、/ Y-(stdafx.hを無効にする)が問題を解決する理由を説明するかもしれ-D_USE_MATH_DEFINESませんが、デフォルトのコンパイラ設定で提供しても問題を解決するのに十分ではない理由を説明するために残ります...問題、追跡することはそれほど明白ではありません...
aka.nice '16年

0

user7860670で提案されているように、プロジェクトを右クリックしてプロパティを選択し、C / C ++-> Preprocessorに移動し_USE_MATH_DEFINESて、Preprocessor Definitionsに追加します。

それが私にとってうまくいきました。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.