Вы можете управлять битами «полезной нагрузки», передавая соответствующие строки в C99 nan
, nanf
, nanl
, но они будут генерировать только тихие значения NaN, а интерпретация строки остается неопределенной (в большинстве реализаций она обрабатывается как шестнадцатеричное число).
В качестве альтернативы используйте союз:
#ifndef __STDC_IEC_559__
#error "This program requires IEEE floating point arithmetic"
#endif
#include <stdint.h>
#include <assert.h>
static_assert(sizeof(float) == sizeof(uint32_t),
"This program requires float to be 32 bits exactly");
float nanf_with_payload_bits(uint32_t payload)
{
if (payload & 0x7FA00000) abort();
union ieee_single {
float f;
uint32_t i;
} nan;
nan.i = 0x7FA00000 | payload;
return nan.f;
}
Запись в один член объединения и последующее чтение из другого, когда оба типа имеют одинаковый размер, НЕ вызывает неопределенное поведение в C99+errata. (Это было неопределенное поведение в C89, но большинство компиляторов определили его для того, чтобы делать то, что вы ожидаете. Это может быть неопределенное поведение в C++, я не уверен; однако, опять же, большинство компиляторов определяют его сделать то, что вы ожидаете.)
Если вы используете эту функцию для создания сигнальных NaN, имейте в виду, что их поведение явно оставлено неопределенным в C99/C11, Приложение F.
НЕ пытайтесь разбить компонент i
объединения на структуру с битовыми полями. Расположение битовых полей в памяти внутри структуры частично определяется реализацией и частично не указано, и, в частности, последовательность битовых полей не обязательно упаковывается в слово в том же порядке, что и ЦП. (или, действительно, должным образом упакованы вообще).
Ссылки на стандарты (все C99):
- такое использование объединения является только неуказанным поведением: 6.2.6.1p7; J.1
- расположение битовых полей в структуре непредсказуемо: 6.2.6.1p1,2; 6.7.2.1п10,11,13; J.3.9
- поведение сигнализации NaN не определено: F.2.1
person
zwol
schedule
28.04.2012