Bug 46908 - printf not handling printing of double correctly in certain cases
Summary: printf not handling printing of double correctly in certain cases
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 4.5.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-12-12 16:12 UTC by Adrian Hawryluk
Modified: 2010-12-13 18:28 UTC (History)
1 user (show)

See Also:
Host: Windows XP SP2
Target: mingw32
Build: 4.5.0
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Adrian Hawryluk 2010-12-12 16:12:17 UTC
This is a weird one.  Under different compile options, it does it wrong in different ways. :)

#include <stdio.h>
#include <math.h>
void printld(long double* pld)
{
    int i;
    printf("*%p = ", pld);
    for (i = 0; i < sizeof(long double); ++i) {
        printf("%02x ", ((unsigned char*)pld)[i]);
    }
    printf("\n");
}

int main()
{
    long double number1 = 1.0;
    long double number2 = 1.0;

    printf ("%lf, %lf\n", number1, number2);

    printf ("Enter number1: ");
    scanf ("%lf", &number1);
    printf ("Enter number2: ");
    scanf ("%lf", &number2);

    printf ("%lf, %lf\n", number1, number2);
    printf ("%lf, %lf\n", number1, number1);

    printld(&number1);
    printld(&number2);
    return 0;
}

C:\tmp>gcc -o tmp.exe file.c

C:\tmp>tmp
0.000000, 0.000000
Enter number1: 3
Enter number2: 4
3.000000, 0.000000
3.000000, 0.000000
*0022FF30 = 00 00 00 00 00 00 08 40 ff 3f 00 00
*0022FF20 = 00 00 00 00 00 00 10 40 ff 3f 00 00

C:\tmp>gcc -std=c99 -o tmp.exe file.c

C:\tmp>tmp
1.000000, 1.000000
Enter number1: 3
Enter number2: 4
0.000000, 0.000000
0.000000, 0.000000
*0022ff30 = 00 00 00 00 00 00 08 40 ff 3f 00 00
*0022ff20 = 00 00 00 00 00 00 10 40 ff 3f 00 00

There was even a way of printing the same variable (number1) twice on a line and it would output it twice.  That is why I had put in:

  printf ("%lf, %lf\n", number1, number1);

as a test, but it didn't show up in this test code.

C:\tmp>gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=c:/mingw/bin/../libexec/gcc/mingw32/4.5.0/lto-wrapper.exe
Target: mingw32
Configured with: ../gcc-4.5.0/configure --enable-languages=c,c++,ada,fortran,objc,obj-c++ --disable-sjlj-exceptions --with-dwarf2 --enable-shared --enable-libgomp --disable-win32-registry --enable-libstdcxx-debug --enable-version-specific-runtime-libs --disable-werror --build=mingw32 --prefix=/mingw

Thread model: win32
gcc version 4.5.0 (GCC)
--
A
Comment 1 Andreas Schwab 2010-12-12 16:51:28 UTC
l has no effect on %f.
Comment 2 Manuel López-Ibáñez 2010-12-12 17:32:26 UTC
Use -Wall:

test.c:18: warning: format ‘%f’ expects type ‘double’, but argument 2 has type ‘long double’

which means that %f is not for long double, you should use %Lf and it will work.
Comment 3 Adrian Hawryluk 2010-12-12 22:53:43 UTC
Sorry, changed to %Lf with same results.   

#include <stdio.h>
#include <math.h>
void printld(long double* pld)
{
    int i;
    printf("*%p = ", pld);
    for (i = 0; i < sizeof(long double); ++i) {
        printf("%02x ", ((unsigned char*)pld)[i]);
    }
    printf("\n");
}

int main()
{
    long double number1 = 1.0;
    long double number2 = 1.0;

    printf ("%Lf, %Lf\n", number1, number2);

    printf ("Enter number1: ");
    scanf (" %Lf", &number1);
    printf ("Enter number2: ");
    scanf (" %Lf", &number2);

    printf ("%Lf, %Lf\n", number1, number2);
    printf ("%Lf, %Lf\n", number1, number1);

    printld(&number1);
    printld(&number2);
    return 0;
}
Comment 4 Adrian Hawryluk 2010-12-12 22:55:47 UTC
But found that "L" is not a known conversion type character.  When is "L" supposed to be implemented?

C:\tmp>gcc -Wall -o tmp.exe file.c
file.c: In function 'main':
file.c:18:5: warning: unknown conversion type character 'L' in format
file.c:18:5: warning: unknown conversion type character 'L' in format
file.c:18:5: warning: too many arguments for format
file.c:21:5: warning: unknown conversion type character 'L' in format
file.c:21:5: warning: too many arguments for format
file.c:23:5: warning: unknown conversion type character 'L' in format
file.c:23:5: warning: too many arguments for format
file.c:25:5: warning: unknown conversion type character 'L' in format
file.c:25:5: warning: unknown conversion type character 'L' in format
file.c:25:5: warning: too many arguments for format
file.c:26:5: warning: unknown conversion type character 'L' in format
file.c:26:5: warning: unknown conversion type character 'L' in format
file.c:26:5: warning: too many arguments for format
Comment 5 Adrian Hawryluk 2010-12-12 23:08:58 UTC
Used flag -std=c99 and this reduced the number of warnings.  They were limited to the scanf format string.

C:\tmp>gcc -Wall -std=c99 -o tmp.exe file.c
file.c: In function 'main':
file.c:21:5: warning: unknown conversion type character 'L' in format
file.c:21:5: warning: too many arguments for format
file.c:23:5: warning: unknown conversion type character 'L' in format
file.c:23:5: warning: too many arguments for format
Comment 6 Joseph S. Myers 2010-12-13 18:28:22 UTC
GCC knows about the limitations of the Windows (msvcrt) printf and scanf functions, which do not support all standard C99 formats, and the warnings are telling you that they are not supported by those libraries.  The MinGW libraries (wrapping msvcrt) are a separate project from GCC and there is no GCC bug here.