The program 
#include <stdio.h>

main()
{
double d;
int i;

    printf("Starting at 32758\n");
    for (d=32758.0, i=0; i<20; i++) {
           printf("d is %f, as integer is 0x%0.8x, and (ushort)d is 0x%0.4x
while (unsigned char)d is 0x%0.2x\n",
                                                                  d, (int)d,
(unsigned short)d, (unsigned char)d);
       d += 1.0;
    }
    return 0;
}
gives the following output on Intel
Starting at 32758
d is 32758.000000, as integer is 0x00007ff6, and (ushort)d is 0x7ff6 while
(unsigned char)d is 0xf6
d is 32759.000000, as integer is 0x00007ff7, and (ushort)d is 0x7ff7 while
(unsigned char)d is 0xf7
d is 32760.000000, as integer is 0x00007ff8, and (ushort)d is 0x7ff8 while
(unsigned char)d is 0xf8
d is 32761.000000, as integer is 0x00007ff9, and (ushort)d is 0x7ff9 while
(unsigned char)d is 0xf9
d is 32762.000000, as integer is 0x00007ffa, and (ushort)d is 0x7ffa while
(unsigned char)d is 0xfa
d is 32763.000000, as integer is 0x00007ffb, and (ushort)d is 0x7ffb while
(unsigned char)d is 0xfb
d is 32764.000000, as integer is 0x00007ffc, and (ushort)d is 0x7ffc while
(unsigned char)d is 0xfc
d is 32765.000000, as integer is 0x00007ffd, and (ushort)d is 0x7ffd while
(unsigned char)d is 0xfd
d is 32766.000000, as integer is 0x00007ffe, and (ushort)d is 0x7ffe while
(unsigned char)d is 0xfe
d is 32767.000000, as integer is 0x00007fff, and (ushort)d is 0x7fff while
(unsigned char)d is 0xff
d is 32768.000000, as integer is 0x00008000, and (ushort)d is 0x8000 while
(unsigned char)d is 0x00
d is 32769.000000, as integer is 0x00008001, and (ushort)d is 0x8001 while
(unsigned char)d is 0x00
d is 32770.000000, as integer is 0x00008002, and (ushort)d is 0x8002 while
(unsigned char)d is 0x00
d is 32771.000000, as integer is 0x00008003, and (ushort)d is 0x8003 while
(unsigned char)d is 0x00
d is 32772.000000, as integer is 0x00008004, and (ushort)d is 0x8004 while
(unsigned char)d is 0x00
d is 32773.000000, as integer is 0x00008005, and (ushort)d is 0x8005 while
(unsigned char)d is 0x00
d is 32774.000000, as integer is 0x00008006, and (ushort)d is 0x8006 while
(unsigned char)d is 0x00
d is 32775.000000, as integer is 0x00008007, and (ushort)d is 0x8007 while
(unsigned char)d is 0x00
d is 32776.000000, as integer is 0x00008008, and (ushort)d is 0x8008 while
(unsigned char)d is 0x00
d is 32777.000000, as integer is 0x00008009, and (ushort)d is 0x8009 while
(unsigned char)d is 0x00

That is, the unsigned char is always zero after 32769.0

On Sparc, with gcc (GCC) 3.3.2, we see
Starting at 32758
d is 32758.000000, as integer is 0x00007ff6, and (ushort)d is 0x7ff6 while
(unsigned char)d is 0xf6
d is 32759.000000, as integer is 0x00007ff7, and (ushort)d is 0x7ff7 while
(unsigned char)d is 0xf7
d is 32760.000000, as integer is 0x00007ff8, and (ushort)d is 0x7ff8 while
(unsigned char)d is 0xf8
d is 32761.000000, as integer is 0x00007ff9, and (ushort)d is 0x7ff9 while
(unsigned char)d is 0xf9
d is 32762.000000, as integer is 0x00007ffa, and (ushort)d is 0x7ffa while
(unsigned char)d is 0xfa
d is 32763.000000, as integer is 0x00007ffb, and (ushort)d is 0x7ffb while
(unsigned char)d is 0xfb
d is 32764.000000, as integer is 0x00007ffc, and (ushort)d is 0x7ffc while
(unsigned char)d is 0xfc
d is 32765.000000, as integer is 0x00007ffd, and (ushort)d is 0x7ffd while
(unsigned char)d is 0xfd
d is 32766.000000, as integer is 0x00007ffe, and (ushort)d is 0x7ffe while
(unsigned char)d is 0xfe
d is 32767.000000, as integer is 0x00007fff, and (ushort)d is 0x7fff while
(unsigned char)d is 0xff
d is 32768.000000, as integer is 0x00008000, and (ushort)d is 0x8000 while
(unsigned char)d is 0x00
d is 32769.000000, as integer is 0x00008001, and (ushort)d is 0x8001 while
(unsigned char)d is 0x01
d is 32770.000000, as integer is 0x00008002, and (ushort)d is 0x8002 while
(unsigned char)d is 0x02
d is 32771.000000, as integer is 0x00008003, and (ushort)d is 0x8003 while
(unsigned char)d is 0x03
d is 32772.000000, as integer is 0x00008004, and (ushort)d is 0x8004 while
(unsigned char)d is 0x04
d is 32773.000000, as integer is 0x00008005, and (ushort)d is 0x8005 while
(unsigned char)d is 0x05
d is 32774.000000, as integer is 0x00008006, and (ushort)d is 0x8006 while
(unsigned char)d is 0x06
d is 32775.000000, as integer is 0x00008007, and (ushort)d is 0x8007 while
(unsigned char)d is 0x07
d is 32776.000000, as integer is 0x00008008, and (ushort)d is 0x8008 while
(unsigned char)d is 0x08
d is 32777.000000, as integer is 0x00008009, and (ushort)d is 0x8009 while
(unsigned char)d is 0x09

Which seems more intuitively correct.
This problem is also found on a XEON proccessor with 
gcc (GCC) 3.2.3 20030502 (Red Hat Linux 3.2.3-47)


-- 
           Summary: Double to char conversion fails at 32769.0
           Product: gcc
           Version: 3.4.5
            Status: UNCONFIRMED
          Severity: major
          Priority: P3
         Component: c
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: barryb at cwipapps dot net
 GCC build triplet: gcc (GCC) 3.4.5 20051201 (Red Hat 3.4.5-2)
  GCC host triplet: 2.6.9-34.0.1.ELsmp #1 SMP Wed May 24 08:14:29 CDT 2006
                    i686 i686
GCC target triplet:  Pentium III (Coppermine)


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=28038

Reply via email to