admin管理员组

文章数量:1026989

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:

  • Is this a bug in MSVC or valid behaviour?
  • What is a robust workaround that won't break the code with other compilers?

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

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:

  • Is this a bug in MSVC or valid behaviour?
  • What is a robust workaround that won't break the code with other compilers?

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

Share Improve this question edited Nov 18, 2024 at 12:25 Szabolcs asked Nov 16, 2024 at 12:29 SzabolcsSzabolcs 25.7k11 gold badges88 silver badges187 bronze badges 9
  • GodBolt appears to have no problem with x64 MSVC v19 latest: godbolt./z/obbsb6znn – pmg Commented Nov 16, 2024 at 12:42
  • I know, it doesn't have the latest MSVC. It seems this affects 17.12, but not 17.11. Godbolt has 17.10. – Szabolcs Commented Nov 16, 2024 at 12:43
  • 1 Found some discussion: github/protocolbuffers/protobuf/issues/17308 and developercommunity.visualstudio/t/… – Szabolcs Commented Nov 16, 2024 at 12:44
  • NAN must be a constant expression. If it isn't, then that's a compiler/library bug. – user17732522 Commented Nov 16, 2024 at 12:46
  • 1 Also, this is obviously not a duplicate. The question is entirely different. Please don't abuse closing powers. This is exactly why StackOverflow is getting such a bad reputation recently. – Szabolcs Commented Nov 16, 2024 at 22:49
 |  Show 4 more comments

2 Answers 2

Reset to default 3

This seems to be a bug in Windows SDK version 10.0.26100.0, which defines NAN as a call to __ucrt_int_to_float() instead of as a constant. It is being tracked here.

As a workaround one can define _UCRT_NOISY_NAN to enable the legacy definition of the NAN macro, which can be seen here.

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 type float 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

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:

  • Is this a bug in MSVC or valid behaviour?
  • What is a robust workaround that won't break the code with other compilers?

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

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:

  • Is this a bug in MSVC or valid behaviour?
  • What is a robust workaround that won't break the code with other compilers?

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

Share Improve this question edited Nov 18, 2024 at 12:25 Szabolcs asked Nov 16, 2024 at 12:29 SzabolcsSzabolcs 25.7k11 gold badges88 silver badges187 bronze badges 9
  • GodBolt appears to have no problem with x64 MSVC v19 latest: godbolt./z/obbsb6znn – pmg Commented Nov 16, 2024 at 12:42
  • I know, it doesn't have the latest MSVC. It seems this affects 17.12, but not 17.11. Godbolt has 17.10. – Szabolcs Commented Nov 16, 2024 at 12:43
  • 1 Found some discussion: github/protocolbuffers/protobuf/issues/17308 and developercommunity.visualstudio/t/… – Szabolcs Commented Nov 16, 2024 at 12:44
  • NAN must be a constant expression. If it isn't, then that's a compiler/library bug. – user17732522 Commented Nov 16, 2024 at 12:46
  • 1 Also, this is obviously not a duplicate. The question is entirely different. Please don't abuse closing powers. This is exactly why StackOverflow is getting such a bad reputation recently. – Szabolcs Commented Nov 16, 2024 at 22:49
 |  Show 4 more comments

2 Answers 2

Reset to default 3

This seems to be a bug in Windows SDK version 10.0.26100.0, which defines NAN as a call to __ucrt_int_to_float() instead of as a constant. It is being tracked here.

As a workaround one can define _UCRT_NOISY_NAN to enable the legacy definition of the NAN macro, which can be seen here.

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 type float 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

本文标签: cRecent MSVC versions don39t treat NAN as constantWorkaroundStack Overflow