Define NaN in portable C without "error C2124: divide or mod by zero"

Viewed 70

I have an old legacy code written in pure C. It's crossplatform. I need to define a NaN constant in it. My approach was: const double _NAN = 0.0/0.0;
Unfortunately when I tried to build the code on Win machine (VS 2022) I've got "error C2124: divide or mod by zero".

I'm pretty sure there is a parameter for parameter for MSVC compiler that disables it, but that's a public project and MS VS is only one of IDE which could be used to build it. And I don't want ask users to change defaults in a specific environment.

I guess I could use HEX value for NaN but suppose I'll face with endiannes... Which imply i'll need to detect endiannes in portable way.

Are there any better options to define NaN for double in C in a crossplatform way?

2 Answers

You can include <math.h> and use NAN. C 1999 and C 2018 7.12 5 both say:

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.

You can use it for the double type, and, if you want to deal with cases in which it is not defined by the C implementation, you can test with #if defined NAN.

If you can't rely on the existence of C99's NAN constant, another way to compute NaN is by subtracting Inf from Inf. If your compiler supports infinity and NaN at all, HUGE_VAL should be a double-precision infinity. Thus, I suggest something like

#include <float.h>
#include <math.h>
#include <stdio.h>

static const double qnan = HUGE_VAL - HUGE_VAL;

int main(void) {
    printf("qnan = %g (%a) isnan(qnan) = %d\n", qnan, qnan, isnan(qnan));
    return 0;
}

If the compiler doesn't support infinity and NaN, then HUGE_VAL will be the largest possible finite number and HUGE_VAL - HUGE_VAL will be zero, so you can check whether this worked with assert(mynan != 0).

Related