Подтвердить что ты не робот

M_PI работает с math.h, но не с cmath в Visual Studio

Я использую Visual Studio 2010. Я прочитал, что в С++ лучше использовать <cmath>, а не <math.h>.

Но в программе я пытаюсь написать (консольное приложение Win32, пустой проект), если я пишу:

#define _USE_MATH_DEFINES
#include <math.h>

он компилируется, а если я пишу

#define _USE_MATH_DEFINES
#include <cmath>

он терпит неудачу с

ошибка C2065: "M_PI": необъявленный идентификатор

Это нормально? Это имеет значение, если я использую cmath или math.h? Если да, как я могу заставить его работать с cmath?

UPDATE: если я определяю _USE_MATH_DEFINES в графическом интерфейсе, он работает. Есть ли подсказки, почему это происходит?

4b9b3361

Ответ 1

Интересно, что я проверил это на своем приложении и получил ту же ошибку.

Я потратил некоторое время, проверяя заголовки, чтобы увидеть, нет ли чего-то, что не было бы отключено _USE_MATH_DEFINES и ничего не найдено.

Итак, я переместил

#define _USE_MATH_DEFINES
#include <cmath>

чтобы быть первым делом в моем файле (я не использую PCH, поэтому, если вам это нужно, вам придется иметь его после #include "stdafx.h" ), и вдруг он скомпилируется отлично.

Попробуйте переместить его вверх по странице. Полностью не уверен, почему это может вызвать проблемы.

Изменить. Выяснилось. #include встречается в защитных оболочках cmath. Это означает, что что-то выше в списке #includes включает cmath без указанного #define. math.h специально разработан так, что вы можете включить его снова с тем определением, которое теперь изменилось, чтобы добавить M_PI и т.д. Это не так с cmath. Поэтому вам нужно убедиться, что вы #define _USE_MATH_DEFINES, прежде чем включать что-либо еще. Надеюсь, что это очистит для вас:)

В противном случае просто включите math.h, вы используете нестандартный C/С++, как уже указывалось:)

Изменить 2. Или, как указывает Дэвид в комментариях, просто сделайте себе константу, которая определяет значение, и у вас есть что-то более портативное в любом случае:)

Ответ 2

Рассмотрите возможность добавления переключателя /D _USE_MATH_DEFINES в командную строку компиляции или для определения макроса в настройках проекта. Это перетащит символ во все доступные темные углы файлов include и source, оставляя ваш источник чистым для нескольких платформ. Если вы установите его глобально для всего проекта, вы не забудете его позже в новом файле.

Ответ 3

Это работает для меня:

#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 нет предварительно скомпилированных заголовков.

Ответ 4

Это все еще проблема в VS Community 2015 и 2017 при создании консольных или оконных приложений. Если проект создан с предварительно скомпилированными заголовками, предварительно скомпилированные заголовки, по-видимому, загружаются до в любой из #includes, поэтому даже если #define _USE_MATH_DEFINES - это первая строка, она не будет компилироваться. #including math.h вместо cmath не имеет значения.

Единственные решения, которые я могу найти, - либо начать с пустого проекта (для простых консольных или встраиваемых системных приложений), либо добавить /Y - в аргументы командной строки, что отключает загрузку предварительно скомпилированных заголовков.

Информацию об отключении предварительно скомпилированных заголовков см., например, https://msdn.microsoft.com/en-us/library/1hy7a92h.aspx

Было бы неплохо, если бы MS изменила/исправила это. Я преподаю вводные курсы программирования в большом университете, и объясняя это, новички никогда не погружаются, пока они не совершили ошибку и не боролись с ней на второй день или около того.