using:
MinGW gcc.exe (i686-posix-dwarf-rev1, Built by MinGW-W64 project) 4.9.2
MSYS2 in Windows 7
atof is not C standard compliant for "-inf", "inf", "-NaN", "NaN", "+NaN" (including all ignoring cases variations) as described at ISO/IEC 9899:1999, sections 7.20.1.1 & 7.20.1.3. It returns 0., but it should return infinity and quiet-NaN values for which there are valid representations under IEEE 754, as it does in Linux.
minimal case(s):
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char s[256]; strcpy(s, "-inf"); printf("atof(\"%s\") = %.17g\n", s, atof(s)); strcpy(s, "inf"); printf("atof(\"%s\") = %.17g\n", s, atof(s)); strcpy(s, "-NaN"); printf("atof(\"%s\") = %.17g\n", s, atof(s)); strcpy(s, "nan"); printf("atof(\"%s\") = %.17g\n", s, atof(s)); strcpy(s, "+NAN"); printf("atof(\"%s\") = %.17g\n", s, atof(s)); return 1; }
gives output:
$ ./a.exe atof("-inf") = 0 atof("inf") = 0 atof("-NaN") = 0 atof("nan") = 0 atof("+NAN") = 0
Please make it standard compliant, or if there is a strong reason why this is already not done (maybe even intentionally implemented as it is now), please introduce compiler flag to enforce it.
Thanks!
Diff:
Thanks for bringing this to our attention. We would point out that this is the bug tracker for products published by MinGW.org; these include neither the mingw-w64 GCC, nor the MSYS2 tools, which you are using; thus, while we will investigate the extent to which this issue affects our own products, we cannot help with products of unrelated projects.
Do please note that our implementation of GCC uses the
atof()
function from Microsoft's MSVCRT.DLL runtime library, and I believe mingw-w64 does likewise. The behaviour you are reporting is a feature of that Microsoftatof()
implementation, so perhaps you should ask them to "fix" it.Diff:
FWIW, I can work around this, (with our
<stdlib.h>
implementation), by adding#define atof(S) (double)(strtold((S),NULL))
to my source file, after including the headers, and compiling with the-posix
option; (without-posix
, I get Microsoft's-1.#INF
,1.#INF
,-1.#IND
,-1.#IND
, and-1.#IND
representations of the results, which is still non-standard, but likely better than zeros).This work around suggests a possible simple resolution, for our products, to be incorporated into
<stdlib.h>
within a__USE_MINGW_ANSI_STDIO
(internal) conditional compilation guard.Thank you for your comments and attention. Your workaround is really elegant!
Why (double) cast for strtold(...), why not just strtod(...)?
strtod()
is still Microsoft's implementation, and similarly ignores ISO-C standards. OTOH,strtold()
is a MinGW.org extension, which aims for ISO-C conformity. You need the standards conforming behaviour of ourstrtold()
implementation, and you then need to cast that to whatever type your application requires.BTW, do be aware that GCC's
long double
is a full 80-bit precision type, whereas in Microsoft's (non-)implementation, it is no more than an alias for their 64-bitdouble
type. If you uselong doubles
, you need to be aware of this difference, particularly w.r.t. I/O; Microsoft's I/O routines cannot process 80-bitlong double
s; MinGW.org offers an extendedprintf()
implementation, (activated by compiling with-posix
,-ansi
, or any of the-std=c...
options to GCC, or by defining_GNU_SOURCE
,_BSD_SOURCE
,_POSIX_SOURCE
,_XOPEN_SOURCE=...
, or_POSIX_C_SOURCE=...
in your sources, before including any system header), which does interpret them correctly.I get correct result with strtod(...), looks like only atof(...) is the problem:
w/o -posix
-posix
But you are not using our tools! I'm only interested in a solution that works for us; whatever other projects may do is irrelevant.
Consider the following variation on your original test case:
Compile and run it on Win7 Home Edition, with or without
-posix
, and I see:Change it, to use
strtold()
rather thanstrtod()
:and the results now become:
We use Microsoft's
strtod()
implementation, (from the platform MSVCRT.DLL), but our ownstrtold()
. Maybe other projects also substitute their ownstrtod()
, but that's irrelevant for us -- we need to use ourstrtold()
, to ensure that we get standard conforming interpretation of infinities and NaNs.Is there a list of MSVC (in)dependent MinGW (your project) methods available?
There is an existing
__strtod()
implementation inlibmingwex.a
, which works correctly; (it also handles hexadecimal-float notation correctly, unlike Microsoft'sstrtod()
implementation). Astatic __inline__
mapping ofstrtod()
to__strtod()
was removed from MinGW.org's<stdlib.h>
in May-2011, (inappropriately, IMO), to circumvent an upstream bug in GCC'slibquadmath
, (which is where it should have been fixed).I've committed [987711], which reinstates the
static __inline__
mapping ofstrtod()
to__strtod()
, and adds a corresponding mapping foratof()
, but now guarded by__USE_MINGW_ANSI_STDIO
; thus, explicitly defining any of the feature test macros which enables__USE_MINGW_ANSI_STDIO
, (which you really should not define directly), or compiling with-posix
,-ansi
, or any of the-std=c...
options, will allow your code to benefit from the remappedstrtod()
call.FWIW, I've compiled a cross-native build of gcc-4.9.3, (building on a GNU/Linux host), using the modified mingwrt; the
libquadmath
issue did not arise. I would be grateful if others will also test this modification.Related
Commit: [987711]