Использование M_PI со стандартом C89

Я использую C и пытаюсь получить доступ к константе M_PI (3.14159 ...). Я импортировал файл заголовка math.h, но константа M_PI все еще не определена. Путем поиска в StackOverflow я обнаружил, что мне нужно добавить #define _USE_MATH_DEFINES в свой код (см. Пример кода ниже). Это нормально работает при обычной компиляции, но мне нужно иметь возможность компилировать с флагом std=c89 для работы, которую я выполняю.

Как мне получить доступ к M_PI из некоторого кода C89?


person robintw    schedule 15.02.2011    source источник


Ответы (4)


Соответствующий файл стандартной библиотеки math.h не только не требуется, но фактически не должен определять M_PI по умолчанию. В этом контексте «по умолчанию» означает, что M_PI должен определяться только с помощью специфичных для компилятора уловок, чаще всего неопределенного поведения с использованием зарезервированных идентификаторов.

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

person eq-    schedule 15.02.2011
comment
@Jason S: это просто следствие того факта, что реализация стандартной библиотеки не может загрязнять пространство имен (т.е. должна использовать только зарезервированные идентификаторы в соответствии со стандартом). - person eq-; 16.02.2011
comment
Это так? Это означало бы, что реализация C никогда не сможет соответствовать C89 и C99 одновременно, поскольку C99 добавляет идентификаторы в библиотеку. - person Fred Foo; 07.03.2012
comment
@larsmans: C99 осторожно добавляет идентификаторы, которые были зарезервированы для реализации в C89 (см., в частности, раздел 4.13 БУДУЩИЕ НАПРАВЛЕНИЯ БИБЛИОТЕКИ в C89) или в новые файлы заголовков, которые не были определены в C89. Однако есть некоторые угловые случаи различного поведения библиотеки между C89 и C99 - например, strtod(), который должен обрабатывать шестнадцатеричные числа с плавающей запятой в C99 и не может в C89. - person caf; 07.03.2012
comment
@FredFoo Это правильно; невозможно одновременно соответствовать стандартам C89 и C99. Вот почему у нас есть переключатели компилятора для выбора того или другого. Реализация C89 может предоставлять некоторые функции C99 как соответствующие расширения; очевидная ситуация позволяет программе вызывать функции C99 или использовать long long (пока выдается диагностика). - person Kaz; 13.09.2018

Я бы пошел на

#ifndef M_PI
#    define M_PI 3.14159265358979323846
#endif
person Sven Marnach    schedule 15.02.2011

M_PI не требуется стандартом C, это просто обычное расширение, поэтому, если вы хотите быть стандартным, вам не следует на него полагаться. Однако вы можете легко определить для него свою #define, в прошлый раз я проверил, что это универсальная константа, поэтому нет места для путаницы. :)

person Matteo Italia    schedule 15.02.2011

Я не понимаю, в чем проблема; нет несовместимости между -std = c89 и _USE_MATH_DEFINES, один определяет, какой язык будет компилировать компилятор, другой определяет, какие части math.h будут включены.

Те части, которые включены, не определены как часть стандартной библиотеки ISO C, но это не то же самое, что не быть стандартным языком C, язык и библиотека являются отдельными объектами в C. менее совместим с C89, чем был бы, если бы вы определили свои собственные макросы в собственном заголовке.

Однако я бы посоветовал вам определить макрос в командной строке, а не в коде:

-std=c89 -D_USE_MATH_DEFINES

Если вы когда-нибудь встретите реализацию math.h, которая не определяет M_PI, то это легко исправить без модификации кода, аналогичным образом используя макросы, определенные в командной строке:

-std=c89 -DM_PI=3.14159265358979323846
person Clifford    schedule 15.02.2011
comment
_USE_* является частью внутренней структуры glibc, предназначенной для определения только features.h в результате определения некоторого общедоступного макроса функционального тестирования. Используйте -D_GNU_SOURCE или, чтобы быть более портативным, -D_XOPEN_SOURCE=700 или подобное. - person R.. GitHub STOP HELPING ICE; 10.06.2013
comment
@R ..: Это ОП решил использовать макрос после того, как нашел его в другом месте на StackOverflow - к сожалению, он не смог указать где. В документации GNU говорится, что для определения _BSD_SOURCE или _XOPEN_SOURCE=500, или более общий макрос выбора функции, тогда как Microsoft C В документации среды выполнения говорится, что необходимо определить _USE_MATH_DEFINES, поэтому я бы остановился на последнем только для совместимости; в вопросе не упоминается какой-либо конкретный компилятор. - person Clifford; 10.06.2013