DOCUMENT:Q44816 22-JUL-2001 [visualc] TITLE :PRB: printf() Appears to Print Incorrect Results for Floats PRODUCT :Microsoft C Compiler PROD/VER:5.1 6.0 6.0a 6.0ax 7.0 1. OPER/SYS: KEYWORDS:kbCRT kbVC kbVC100 kbVC150 kbVC151 kbVC152 kbVC200 kbVC210 kbVC400 kbVC500 kbVC600 ====================================================================== ------------------------------------------------------------------------------- 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, 16-bit edition, versions 1.0, 1.5, 1.51, 1.52 - Microsoft Visual C++, 32-bit Editions, versions 1.0, 2.0, 2.1, 4.0, 5.0, 6.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 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. Additional query words: ====================================================================== Keywords : kbCRT kbVC kbVC100 kbVC150 kbVC151 kbVC152 kbVC200 kbVC210 kbVC400 kbVC500 kbVC600 Technology : kbVCsearch kbAudDeveloper kbCRT Version : 5.1 6.0 6.0a 6.0ax 7.0 1. 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. Copyright Microsoft Corporation 2001.