M_PI, math.h ile çalışır ancak Visual Studio'da cmath ile çalışmaz


96

Visual Studio 2010 kullanıyorum. C ++ 'da kullanmak <cmath>yerine kullanmanın daha iyi olduğunu okudum <math.h>.

Ama programda yazmaya çalışıyorum (Win32 konsol uygulaması, boş proje) yazarsam:

#define _USE_MATH_DEFINES
#include <math.h>

derler, ben yazarsam

#define _USE_MATH_DEFINES
#include <cmath>

ile başarısız olur

hata C2065: 'M_PI': bildirilmemiş tanımlayıcı

Bu normal mi? Cmath veya math.h kullanmam fark eder mi? Varsa, cmath ile nasıl çalışmasını sağlayabilirim?

GÜNCELLEME : GUI'de _USE_MATH_DEFINES'i tanımlarsam çalışır. Bunun neden olduğuna dair bir fikriniz var mı?


Kaynak dosyalarınız .c veya .cpp mi?
İsviçre

1
İsviçre: burada önemli olmamalı.
rubenvb

Çok garip ... VS2010 ile aynı sorunu yaşadığımı doğrulayabilirim ... tanımın geçmesini engelleyen şeyi araştırıyorum ... bir yerde tanımlanmamış olmalı ... ama nerede olduğunu anlayamıyorum
Goz

X86 ile, C2065 hatasını şikayet eder. X64 ile hata olmaz.
user2616989

Yanıtlar:


117

İlginç bir şekilde bunu bir uygulamamda kontrol ettim ve aynı hatayı aldım.

Bir süre üstbilgileri kontrol ederek bir şey olup olmadığını kontrol ettim _USE_MATH_DEFINESve hiçbir şey bulamadım.

Ben de taşıdım

#define _USE_MATH_DEFINES
#include <cmath>

dosyamdaki ilk şey olmak (PCH kullanmıyorum, bu yüzden eğer öyleyse, sonra ona sahip olmak zorunda kalacaksın #include "stdafx.h") ve aniden mükemmel bir şekilde derleniyor .

Sayfanın yukarısına taşımayı deneyin. Yine de bunun neden sorunlara neden olacağından tamamen emin değilim.

Düzenleme : Anladım. #include <math.h>Cmath en başlık korumaları içinde gerçekleşir. #İncludes listesinde daha yukarı bir şey dahil olduğunu bu araçlar cmatholmadan #definebelirtildi. math.hözel olarak, şimdi eklemek için değiştirilen tanımla tekrar dahil edebilmeniz için tasarlanmıştır . M_PIDurum böyle DEĞİLDİR cmath. Bu yüzden emin olmalısın#define _USE_MATH_DEFINES başka bir şey eklemeden önce . Umarım bu sizin için çözer :)

Başarısızlık, math.hzaten belirtildiği gibi standart olmayan C / C ++ kullanıyorsunuz :)

Düzenleme 2 : Veya David'in yorumlarda belirttiği gibi, kendinizi değeri tanımlayan bir sabit yapın ve yine de daha taşınabilir bir şeye sahip olursunuz :)


Daha önce tanımlamış stdafx.holmak, bu davranışla daha önce karşılaştığım OP'lerin sorunudur.
Alok Save

@Als: Hayır, o değil ... kırdım ve yukarıdaki düzenlememde açıkladım :)
Goz

Yapılması gereken ilk şey buydu, bunu diğer huysuzların üstünde tutun. OP'den aynısını yapmasını istedim ... Her neyse, cevabınız neden standart başlıklardan önce olması gerektiğini söylediği için cevabımı silecek.
Alok Save

3
Bu davranışı, örneğin, sizden önce #include <math.h> 'ye başka bir şey olsaydı alırsınız. Bununla birlikte, standartta <cmath> öğesinin <math.h> içermesi gerektiğini veya <math.h> içindeki standart olmayan tanımları etkinleştirmesi gerektiğini söyleyen hiçbir şey yoktur. Maalesef M_PI standart değildir. Taşınabilirlik için yapılacak en iyi şey, onu kendiniz tanımlamaktır. Daha da iyisi, onu const static double# tanımlı bir değer yerine bir değer yapın.
David Hammen

1
@David Hammen: Kabul edildi .. Kendini tanımlamak kesinlikle en taşınabilir seçenek :)
Goz

14

Derleme komut satırınıza / D_USE_MATH_DEFINES anahtarını eklemeyi veya proje ayarlarında makroyu tanımlamayı düşünün. Bu, simgeyi dahil etme ve kaynak dosyalarının tüm erişilebilir karanlık köşelerine sürükleyerek kaynağınızı birden çok platform için temiz bırakır. Bunu tüm proje için global olarak ayarlarsanız, daha sonra yeni dosya (lar) da unutmayacaksınız.


Muhtemelen VisualStudio'dan çalıştırırken iyi bir cevap, ancak Matlab mex komut satırı (kullandım mex -D_USE_MATH_DEFINES) aracılığıyla derlerken benim için sorunu çözmediğini unutmayın . Sadece /Y-bazı Matlab mexoptions dosyalarına sms yerleştirmek yardımcı oldu ...
aka.nice

10

Bu benim için çalışıyor:

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

using namespace std;

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

    return 0;
}

Derler ve baskılar pigibi DİSK yapmalıdır: cl /O2 main.cpp /link /out:test.exe.

Gönderdiğiniz kodda ve derlemeye çalıştığınız kodda bir uyuşmazlık olmalı.

.Dosyanızdan önce alınan önceden derlenmiş başlıklar olmadığından emin olun #define.


VisualStudio'nun hangi sürümünü kullanıyorsunuz?
Goz

Aynı program, Visual C ++ 2010 Express Edition'ın komut satırı derleyicisini kullanarak benim için iyi çalıştı. Tek fark, <iostream> 'den std :: cout yerine <cstdio>' dan std :: printf () kullanmış olmam.

5
Evet anladım ... çünkü maths.h, cmath'ın başlık korumalarından çağrıldı ... bu yüzden maths.h, #define seti olmadan daha önceki bir başlıktan dahil edildi :)
Goz

4

Bu, konsol veya Windows uygulamaları oluştururken VS Community 2015 ve 2017'de hala bir sorundur. Proje önceden derlenmiş başlıklarla oluşturulmuşsa, önceden derlenmiş başlıklar görünüşte #includes'ten önce yüklenir , bu nedenle #define _USE_MATH_DEFINES ilk satır olsa bile derlenmez. #include math.h yerine cmath bir fark yaratmaz.

Bulabildiğim tek çözüm, boş bir projeden başlamak (basit konsol veya gömülü sistem uygulamaları için) ya da önceden derlenmiş başlıkların yüklenmesini kapatan komut satırı argümanlarına / Y- eklemek.

Önceden derlenmiş üstbilgileri devre dışı bırakma hakkında bilgi için bkz. Örneğin https://msdn.microsoft.com/en-us/library/1hy7a92h.aspx

MS'in bunu değiştirmesi / düzeltmesi iyi olurdu. Büyük bir üniversitede programlamaya giriş dersleri veriyorum ve bunu yeni başlayanlara açıklamak, hata yapıp bununla bir öğleden sonra kadar uğraşana kadar asla batmaz.


Bilgisayar korsanlığının /
Y'nin

1
Bu, VS'de hiç bir sorun değildir. _USE_MATH_DEFINESherhangi bir başlık eklemeden önce tanımlanmalıdır. Genellikle proje ayarı veya yapılandırma başlığı aracılığıyla. İlk satıra koymanın, tüm başlıklardan önce tanımlanmasına neden olacağını varsaymak yanlıştır.
user7860670

1

Matematik Sabitleri ile ilgili Microsoft belgelerine göre :

Dosya ATLComTime.h, math.hprojenizin Yayın modunda oluşturulduğu zamanı içerir. Ayrıca içeren bir projede matematik sabitlerinden bir veya daha fazlasını kullanırsanız ATLComTime.h, _USE_MATH_DEFINESeklemeden önce tanımlamanız gerekir ATLComTime.h.

Dosya ATLComTime.h, projenize dolaylı olarak dahil edilebilir. Benim durumumda olası bir sıralama şuydu:

proje "stdafx.h"<afxdtctl.h><afxdisp.h><ATLComTime.h><math.h>


Bu, / Y- (stdafx.h'yi devre dışı bırak) 'ın sorunu neden çözeceğini açıklayabilir, ancak yine -D_USE_MATH_DEFINESde varsayılan derleyici ayarlarının sorunu çözmek için neden yeterli olmadığını açıklamaya devam ediyor ... Derleme benim için Matlab mex komutuyla yapıldığından sorun, takip etmesi o kadar açık değil ...
aka. güzel


0

User7860670 tarafından önerildiği gibi, projeye sağ tıklayın, özellikleri seçin, C / C ++ -> Önişlemci'ye gidin ve _USE_MATH_DEFINESÖnişlemci Tanımlarına ekleyin .

Benim için çalışan buydu.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.