The following prints correctly when compiled with the g++ driver (__USE_MINGW_ANSI_STDIO is defined by the driver, verified by the -E -dM switches). However changing the include order so that math.h is included after stdio.h negates the define somehow and thereafter makes the calls the MSVCRT version of printf (with no support for long double).
NOTE 1: explicitly defining -D__USE_MINGW_ANSI_STDIO=1 during compile returns the correct behavior.
NOTE 2: explicitly defining #define __USE_MINGW_ANSI_STDIO=1 prior to inclusion of math.h in the INCORRECT order does not solve the problem.
NOTE 3: Converting to use the cstdio and cmath headers fixes the issue (include order does not affect behavior).
gcc version 7.1.0 (i686-win32-sjlj-rev1, Built by MinGW-W64 project)
so the v5 runtime I guess? (is there a way to find out the runtime release version out of curiosity???)
#include <math.h>
#include <stdio.h>
int main()
{
printf("%.40Lf\n", 3.765625e-31L);
return 0;
}
yes, v5.x branch
patches are welcom ;)
Last edit: niXman 2017-08-16
Oh, I know a patch would be welcome I put this in here so that it's actually known and tracked lol...
I've narrowed it down to the fact that unless something from the libstdc++ header directory is included, nothing will unconditionally define
__USE_MINGW_ANSI_STDIOas the one that is made in bits/os_defines.h via bits/c++config.h. Until and unless a C++ include is made__USE_MINGW_ANSI_STDIOis made based on the decision in_mingw.h. The only time__cplusplushas any effect in that decision in the mingw header is if_GNU_SOURCEis also defined, meaning that in and of itself, compiling with the C++ driver, while apparantly wanting to use the ANSI implementation, doesn't actually do so all the time.Of course, the reason that including the C++ versions in any order makes it work is that they include the appropriate bits...and also the reason that including certain C headers makes it work is that the first directory searched is the libstdc++ directory for the header (which includes the c++config.h and os_config. There are a few headers that will do this if included before stdio.h: math.h stdlib.h fenv.h being a couple of them.
Compounding the issue is that if stdio.h has already been included, and then one of the c++ headers is included, the
__USE_MINGW_ANSI_STDIOis redefined at that point, but the incorrect guarded bits are already brought in leading to the different behavior dependent upon include ordering.The question becomes: does this need to be fixed within the CRT (e.g. changing the decision of when to set the
__USE_MINGW_ANSI_STDIOor is this actually an issue that needs to be changed in the stdc++ header directory?ummm, capital L? that isn't in the format spec is it?
long double is %Lf and has been since at least C99 if not longer. The MS CRT is not compliant (well the one that mingw links against) with respect to the format specifier (many systems still have the MSVCRT.DLL versions that don't have the compliant functionality). In addition, the MS CRT afaik doesn't utilize long double and most of its functions treat long double the same as a double (e.g. long double functions are just mapped to casted version of double). This is why the
__USE_MINGW_ANSI_STDIOmacro exists in the first place.correct with 64bit gcc
No. It is not. Reordering the include files gives different results. Regardless of the correctness, I would expect the standard headers to produce the same results regardless of include order (regardless of what the results are)
Mainly because the MS VCRT printf cannot handle the long double type as used by gcc. And that's the problem, is the definition choice of
__USE_MINGW_ANSI_STDIOwhen using the g++ driver. I still honestly don't know what the answer is. Is it check the ISO defined compiler flags? The big one is that gcc mingw64 uses a different long double, while the MSVC compiler uses a downcast-to-double, meaning they don't play well together. But there's no way of knowing which one. The libc++ headers define__USE_MINGW_ANSI_STDIOunconditionally if they are ever included.What is the best solution? I don't know. I don't know the implications of preferring the ANSI stdio over the microsoft one, but the microsoft CRT that's been used for the past 7 years has been a lot more ANSI complaint and maybe checking the various values of
__cplusplus,__STDC__(and...ummm...__STRICT__? whatever the flag that is set that is the difference between -std=c99 vs -std=g99 etc)Calls the mingw ANSI long double printf:
However:
Calls the MSVCRT printf and produces