Double data type C Red Hat platform problem

I'm converting a binary file to ASCII using c code.
The folllowing block of code prints correct double value 00000.000000000 on HPUNIX platform.

 
longi double;
/* C79 - Price Per Minute */  
  memcpy(&longi,&rbuff[503],8);
  fprintf(wfp,"%015.9f ",longi);

prints :

00000.000000000 

however , the same block when executed on Red hat (
gcc version 4.1.2 20080704 (Red Hat 4.1.2-50)
) is not portable with the platform.It prints random digits with length > 180 like 123234342343433423423423423423423423434.3424342342343434234

is there a way make the code working on red hat ?

I'm guessing, but I think one problem is Endianness. The byte order of the 8 bytes copies into the double variable is inverted. Also note you have more than one thing going on here. It looks like you may have compiled K&R code.

  1. you are messing with the order of the bytes
  2. memcpy may not be filling the destination double variable with everything it need in the right places.

Either one of these is called 'undefined behavior'. Undefined behavior means the compiled has no idea what to do with the garbage in the variable. You have to have incurred some kind of exception.

Also note: HPUX uses an ancient version (K&R) C compiler by default which may be why it 'works' there - probably some odd library rather than FP opcodes. Red Hat uses x86 architecture - it has FP operations on FP registers, not a library.

What exactly are the contents of rbuff, anyway?

The code:

longi double;
/* C79 - Price Per Minute */  
  memcpy(&longi,&rbuff[503],8);
  fprintf(afp,"%015.9f ",long);

isn't valid in any C compiler I've ever seen. The 1st line is declaring a variable named double of type longi .

Are we correct in assuming that the 1st was actually:

double longi;

What hardware were you using on the system running HP/UX? In addition to the endianness issue mentioned by Jim McNamara, there can also be differences in byte order within an object of type double when you move from one CPU type to another.

Apologies "double longi;" is not part of the code , i just wanted to inform that longi is of double data type.
i don't have any hardware info for the HP system.

the field i need to extract from binary file is of 8 bytes . it starts from 503 to 511 bytes in the binary file.So i read 8 bytes into longi and then print it .

unsigned char rbuff[1012];
double longi

 /* C79 - Price Per Minute */  
  memcpy(&longi,&rbuff[503],8);
  fprintf(wfp,"%015.9f ",longi);

It likely needs to be byte-swapped.

#include <stdint.h>

void swap64(void *mem) {
        uint64_t x=*((uint64_t *)mem)
        x = (x & 0x00000000FFFFFFFF) << 32 | (x & 0xFFFFFFFF00000000) >> 32;
        x = (x & 0x0000FFFF0000FFFF) << 16 | (x & 0xFFFF0000FFFF0000) >> 16;
        x = (x & 0x00FF00FF00FF00FF) << 8  | (x & 0xFF00FF00FF00FF00) >> 8;
        *((uint64_t *)mem)=x;
}

...

memcpy(&longi,&rbuff[503],8);
swap64(&longi); // Only do this on systems of differing endian from file

Code adapted from here.

1 Like

It worked.

Thank you all.

1 Like