Microsoft KB Archive/44816

From BetaArchive Wiki
< Microsoft KB Archive
Revision as of 10:19, 21 July 2020 by X010 (talk | contribs) (Text replacement - ">" to ">")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Knowledge Base


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

Article ID: 44816

Article Last Modified on 12/12/2003



APPLIES TO

  • The C Run-Time (CRT), when used with:
    • Microsoft Visual C++ 1.0 Professional Edition
    • Microsoft Visual C++ 1.5 Professional Edition
    • Microsoft Visual C++ 1.51
    • Microsoft Visual C++ 1.52 Professional Edition
    • Microsoft Visual C++ 1.0 Professional Edition
    • Microsoft Visual C++ 2.0 Professional Edition
    • Microsoft Visual C++ 2.1
    • Microsoft Visual C++ 4.0 Standard Edition
    • Microsoft Visual C++ 5.0 Standard Edition
    • Microsoft Visual C++ 6.0 Service Pack 5



This article was previously published under Q44816

SUMMARY

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. The problem is that a 2-byte format specifier is being used for an 8-byte value. To correct this problem, replace "%x" and "%lx" with "%lx %lx".

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: kbcrt kbprb KB44816