Для размещенных реализаций C можно сделать #include <math.h>
и использовать макрос NAN
, если он определен.Например, в GCC это реализуется с помощью встроенного: (__builtin_nanf (""))
.
Для автономных реализаций C (для которых заголовок <math.h>
может быть недоступен) или когда макрос NAN
не определен(что может произойти, даже если могут поддерживаться NaN), можно генерировать NaN с помощью операции с плавающей запятой, такой как 0.0 / 0.0
.Однако может возникнуть несколько проблем с ним.
Во-первых, такая операция также генерирует исключение с возможной ловушкой в некоторых реализациях языка Си.Можно убедиться, что он вычисляется во время компиляции с помощью:
static double my_nan = 0.0 / 0.0;
Другая проблема заключается в том, что Microsoft Visual C ++ (по крайней мере, некоторые версии) пытается вычислить 0.0 / 0.0
во время компиляции (даже когда это выражениев произвольном месте в коде) и жалуется на его действительность.Итак, решение здесь противоположное: убедитесь, что компилятор не оценит его во время компиляции, выполнив:
static double zero = 0.0;
, а затем используйте zero / zero
.Поскольку эти решения противоречат друг другу, можно протестировать компилятор с директивами препроцессора (#if
...) на определенных макросах .
Можно также выбрать решение на основе кодирования NaN,но есть и проблемы с переносимостью.Во-первых, стандарт IEEE 754 не полностью определяет кодирование NaN, в частности, способ различать тихие и сигнальные NaN (и аппаратные средства отличаются на практике);сигнальные NaNs приведут к неопределенному поведению.Более того, стандарт IEEE 754 не определяет, как битовая строка представляется в памяти, то есть может потребоваться обнаружение порядка байтов.Если эти проблемы решены, объединение или массив unsigned char
с приведением указателя вполне подходят для получения типа с плавающей точкой.Не используйте целое число с указателем, приведенным к его адресу, чтобы делать типизацию, так как это нарушит правила псевдонимов C.