gcc: printf and long double leads to wrong output. [C – Type conversion messes up]

The problem (after fixing the various problems if using integer specifiers for floating point formatting) is that you’re mixing GCC types with an MSVC runtime that doesn’t understand them.

First off, MinGW is a GCC compiler, but it uses an MSVC runtime for the bulk of it runtime support. What this means for the printf() family of functions is that only the format specifiers that msvcrt.dll supports and only the types that msvcrt.dll supports will work. But GCC doesn’t know anything about this, so it’ll pass its own types and, of course, the format specifiers are whatever you pass in the format string (though GCC might issue warnings that don’t really apply to the msvcrt.dll situation). See Strange “unsigned long long int” behaviour for some examples based on 64-bit ints (I think that newer versions of msvcrt.dll may have fixed some or all of the 64-bit int issues though).

The other part of this problem you’re running into is that long double in GCC is a different type than long double in MSVC. GCC uses a 96-bit or 128-bit type for long double on x86 or x64 targets (see http://gcc.gnu.org/onlinedocs/gcc/i386-and-x86_002d64-Options.html). However, MSVC uses a 64-bit type – basically long double is exactly the same as double for msvcrt.dll (http://msdn.microsoft.com/en-us/library/9cx8xs15.aspx):

Previous 16-bit versions of Microsoft C/C++ and Microsoft Visual C++ supported the long double, 80-bit precision data type. In Win32 programming, however, the long double data type maps to the double, 64-bit precision data type. The Microsoft run-time library provides long double versions of the math functions only for backward compatibility. The long double function prototypes are identical to the prototypes for their double counterparts, except that the long double data type replaces the double data type. The long double versions of these functions should not be used in new code.

So what this boils down to is that the GCC/MinGW long double type will simply not be compatible with the formatted I/O in msvcrt.dll. Either switch to using double with MinGW, or if you need to use long double you’ll have to cast the values to (double) for formatted I/O or come up with your own formatting routines.

Another option might be to use the GCC compiler under Cygwin, which I think will avoid relying on msvcrt.dll for I/O formatting (at the cost of relying on the Cygwin environment).

Leave a Comment