nan
適切な文字列を C99 , nanf
,nanl
関数に渡すことで「ペイロード」ビットを制御できる場合がありますが、これらはquiet NaNのみを生成し、文字列の解釈は指定されていません (ほとんどの実装では、16 進数として扱われます)。
または、共用体を使用します。
#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;
}
両方の型がまったく同じサイズの場合、共用体の 1 つのメンバーに書き込み、次に別のメンバーから読み取ると、C99+errata で未定義の動作が引き起こされることはありません。( C89 では未定義の動作でしたが、ほとんどのコンパイラは、期待どおりの動作を行うように定義しています。C++ ではまだ未定義の動作である可能性がありますが、よくわかりません。ただし、繰り返しになりますが、ほとんどのコンパイラでは、期待どおりの動作を行うように定義されています。 )
この関数を使用してシグナリングNaN を作成する場合は、その動作が C99/C11 Annex F で明示的に未定義のままになっていることに注意してください。
i
共用体のコンポーネントをビットフィールドを持つ構造に分解しようとしないでください。構造内のビット フィールドのメモリ レイアウトは、部分的に実装で定義され、部分的に指定されていません。特に、一連のビット フィールドは、必ずしも CPU のエンディアンと同じ順序でワードにパックされるとは限りません (実際には、適切にパックされます)。まったく)。
標準の引用 (すべて C99):
- この共用体の使用は未規定の動作にすぎません: 6.2.6.1p7; J.1
- 構造内のビットフィールドのレイアウトは予測できません: 6.2.6.1p1,2; 6.7.2.1p10,11,13; J.3.9
- シグナリング NaN の動作は定義されていません: F.2.1