C2x (as well as previous):
The macro
NAN
is defined if and only if the implementation supports quiet NaNs for thefloat
type. It expands to a constant expression of type float representing a quiet NaN.
Sample code (t0a.c)
#include <stdio.h>
#include <math.h>
#include <fenv.h>
#if _MSC_VER && ! __clang__ && ! __INTEL_COMPILER
#pragma fenv_access (on)
#else
#pragma STDC FENV_ACCESS ON
#endif
void print_fe_excepts_raised(void)
{
printf("exceptions raised ");
if (fetestexcept(FE_DIVBYZERO)) printf(" FE_DIVBYZERO");
if (fetestexcept(FE_INEXACT)) printf(" FE_INEXACT");
if (fetestexcept(FE_INVALID)) printf(" FE_INVALID");
if (fetestexcept(FE_OVERFLOW)) printf(" FE_OVERFLOW");
if (fetestexcept(FE_UNDERFLOW)) printf(" FE_UNDERFLOW");
if (fetestexcept(FE_ALL_EXCEPT)==0) printf(" none");
printf("\n");
}
int main(void)
{
float f;
feclearexcept(FE_ALL_EXCEPT);
f = NAN;
print_fe_excepts_raised();
(void)f;
return 0;
}
Invocations:
# msvc (version 19.29.30133 for x64)
$ cl t0a.c /std:c11 /Za /fp:strict && t0a.exe
exceptions raised FE_INEXACT FE_INVALID FE_OVERFLOW
# clang on Windows (version 13.0.0)
$ clang t0a.c -std=c11 -pedantic -Wall -Wextra -ffp-model=strict && ./a.exe
exceptions raised FE_INEXACT FE_INVALID FE_OVERFLOW
# gcc on Windows (version 11.2.0)
$ gcc t0a.c -std=c11 -pedantic -Wall -Wextra && ./a.exe
exceptions raised none
# gcc on Linux (version 11.2.0)
$ gcc t0a.c -std=c11 -pedantic -Wall -Wextra && ./a.out
exceptions raised none
# clang on Linux (version 13.0.0)
$ clang t0a.c -std=c11 -pedantic -Wall -Wextra -ffp-model=strict && ./a.out
exceptions raised none
For msvc and clang on Windows: this is because:
C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt\corecrt_math.h:94:9
#define NAN ((float)(INFINITY * 0.0F))
C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt\corecrt_math.h:90:9
#define INFINITY ((float)(_HUGE_ENUF * _HUGE_ENUF))
C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt\corecrt_math.h:87:13
#define _HUGE_ENUF 1e+300 // _HUGE_ENUF*_HUGE_ENUF must overflow
Here we see that NAN
"expands to a constant expression of type float representing a quiet NaN". Which implies that f = NAN
may cause floating-point exceptions. However, f = NAN
is usually seen as "writing to memory". Hence, people may wonder: "how writing to memory may cause raising floating-point exceptions?".