Recent MSVC versions don't seem to treat NAN
as a constant anymore. The new definition appears to be (__ucrt_int_to_float(0x7FC00000))
. The old one was (-(float)(((float)(1e+300 * 1e+300)) * 0.0F))
.
This causes code like the following to fail to compile with error C2099: initializer is not a constant
:
#include <math.h>
double x[] = { 1.0, NAN };
Unfortunately, I don't have direct access to MSVC and I am dealing with this through GitHub CI.
Questions:
Apparently, MSVC also doesn't accept 0.0 / 0.0
. The code double f() { return 0.0 / 0.0; }
fails with error C2124: divide or mod by zero
This is a bug in MSVC.
The NAN
macro is required to be a constant expression. Such expressions are allowed in file scope initializers as they can be evaluated at compile time.
This is mandated in section 7.12p6 of the C99 standard:
The macro
NAN
is defined if and only if the implementation supports quiet NaNs for the
float
type. It expands to a constant expression of typefloat
representing a quiet NaN.
The same language exists in C11 and C23.
This it's the first time that MSVC has exhibited non standard compliant behavior.
To work around this, you can check the MSVC version by inspecting the _MSC_VER
macro. For MSVC 17.12, the internal version number is 19.42 which translates to a macro value of 1942. Based on this, you can redefine NAN
to what is was previously.
#include <math.h>
#ifdef _MSC_VER
# if _MSC_VER >= 1942
# undef NAN
# define NAN (-(float)(((float)(1e+300 * 1e+300)) * 0.0F))
# endif
#endif