PRB: printf() Appears to Print Incorrect Results for Floats

Last reviewed: July 24, 1997
Article ID: Q44816
The information in this article applies to:
  • The C Run-time (CRT), included with: - Microsoft C for MS-DOS, versions 5.1, 6.0, 6.0a, 6.0ax - Microsoft C for OS/2, versions 5.1, 6.0, 6.0a - Microsoft C/C++ for MS-DOS, version 7.0 - Microsoft Visual C++ for Windows, versions 1.0, 1.50, 1.51, 1.52 - Microsoft Visual C++, 32-bit Edition, versions 1.0, 2.0, 2.1, 4.0, 5.0

SYMPTOMS

The printf() in the sample code below does not print out the correct values; the float is printed with a hexadecimal specifier before the float specifier.

CAUSE

The problem is that a 2-byte format specifier is being used for an 8-byte value.

RESOLUTION

To correct this problem, replace "%x" and "%lx" with "%lx %lx".

MORE INFORMATION

Sample Code

   /* Compile options needed: none
   */

   #include <stdio.h>
   main()
   {
      float flt  = 1.701411e+038;
      double dbl = 1.701411e+038;

      printf("\nFLOAT         %x   %e", flt,flt);
      printf("\nDOUBLE        %lx  %le",dbl,dbl);
   }

The above code produces incorrect output. However, the source code is incorrect. When printing, the above code is using a 2-byte hex format specifier %x or a 4-byte hex format specifier %lx with an 8-byte double argument (the float is also passed as a double). This produces the incorrect results. To solve this problem, use two %lx format specifiers to remove 8-bytes off the stack before printing the second double. For example:

   printf("\nFloat  %lx %lx %e",flt,flt);
   printf("\nDouble %lx %lx %le",dbl,dbl);

This works correctly for Microsoft C under MS-DOS or OS/2; however, this code may not be portable under other systems that support types of different sizes.

Eight bytes are passed, independent of the fact that one argument is a float and the other a double, because the float is being promoted to a double. This is because all floats are passed as doubles unless they are specified as floats in the prototype. Because printf() has a variable number of parameters, the arguments are not prototyped and therefore all floats are promoted up to doubles.


Keywords : CRTIss
Version : 5.1 6.0 6.0a 6.0ax 7.0 1.
Platform : MS-DOS NT WINDOWS
Issue type : kbprb


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: July 24, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.