64 bit problem

Started by
8 comments, last by iMalc 18 years, 11 months ago
Hello, I recieved 8 bytes of data via socket byte stream and I stored the data in a byte array of unsigned char. I need to place each of these bytes in a long double (8 bytes) in the same order they are in the byte array. The 64 bit float will be using ANSI/IEEE Std 754 format to interpret the value. Ordinarly this would be easy as I could just set up a 8 bit mask and set each byte in the 32 bit value accordingly. However, since it is a 64 bit value, it is not allowing me to do any bit manipulation for some reason. I'm using GCC version 3.8 so I'm not sure if this is an issue. I also tried to set a long double pointer to point towards the first index of the byte array, hoping it would take in the whole 64 bits but it did not work for some reason (possibly my casting was wrong). I feel I'm on the right track but I just can't gather a solution. I hope I am being clear enough? Does anyone have any ideas of how I could get my 64 bit float value out of the 8 bytes in the byte array. Thanks for the help.
Advertisement
Did you try to use unions ?

union {  unsigned char[8];  double d;};

If the data in the array is in fact a 64bit float (double), and stored in the correct byte order, you should be able to just access it as if it was a double (after all, it's just raw binary data).
What probably went wrong in your cast approach, was that you cast to a long double, which is the extended ieee floating point representation - 80bits long.
Your bytes might be reversed (big-endian/little-endian difference). But I would expect one of these pieces of code to work, depending on if you need to reverse the bytes or not:
double ToDouble_NoSwap(unsigned char* ByteArray){  double n;  unsigned char* p = (unsigned char*)&n;  for (int i = 0; i < 8; ++i)    p = ByteArray;  return n;  //Or could just use this code:  //return *((double*)ByteArray);}double ToDouble_WithSwap(unsigned char* ByteArray){  double n;  unsigned char* p = (unsigned char*)&n;  for (int i = 0; i < 8; ++i)    p = ByteArray[7 - i];  return n;}

This is probably somewhat crappy code, but it should get the job done. At least gets the idea across.
"We should have a great fewer disputes in the world if words were taken for what they are, the signs of our ideas only, and not for things themselves." - John Locke
Apparently I was using a long double previously which turns out to be 16 bytes and the extended IEEE format; so that was no good.

I tried both the union and the sample code posted and I get the same answer for both but not the answer I think I should be getting. For example: the floating point 17.5 would equal (in 64 bit IEEE form)
Sign: 0
Exponent: 10000000011 // 4
Mantissa: 000110000000000.... // 10001.1 normalized

Using these values, I just made a byte array with test data to see if it would output the right value.

#include &lt;stdio.h&gt;int main(){    int i;    unsigned char buffer[256];    buffer[0] = 64;    buffer[1] = 49;    buffer[2] = 128;    buffer[3] = 0;    buffer[4] = 0;    buffer[5] = 0;    buffer[6] = 0;    buffer[7] = 0;    unsigned char* ByteArray = &buffer[0];    double n;    unsigned char* p = (unsigned char*)&n;    for(i=0; i &lt; 8; ++i)        p = ByteArray;    printf("The value of n is:  %d\n", n);    return 0;}

Output:
The value of n is: 1076985856


Does the code work correctly or is it just my test data that is wrong? Thanks again for the help.
If your system is little endian, the lowest byte is stored first.
So you may turn around the bytes:
#include <iostream>using namespace std;       int main(){        double d;    unsigned char* buffer = (unsigned char*)&d;    buffer[0] = 0;    buffer[1] = 0;    buffer[2] = 0;    buffer[3] = 0;    buffer[4] = 0;    buffer[5] = 0x80;    buffer[6] = 0x31;    buffer[7] = 0x40;    cout << "d: " << d << endl;        return 0;}


Result is:
d: 17.5
Very strange, when I use the C++ version (using cout and g++ compiler) I get 17.5, but when I use the C version (with printf and gcc compiler) it gives me the 1076985856 number. But at least I know it is being interpretted right (the C++ version shows that). Anyone have any ideas why I am not getting the right answer with C?
Quote:Original post by Elwren
Very strange, when I use the C++ version (using cout and g++ compiler) I get 17.5, but when I use the C version (with printf and gcc compiler) it gives me the 1076985856 number. But at least I know it is being interpretted right (the C++ version shows that). Anyone have any ideas why I am not getting the right answer with C?
Are you using the correct formatting code with printf?
"Walk not the trodden path, for it has borne it's burden." -John, Flying Monk
I'm using printf("%d", nameOfDouble);
I tried adding the modifer printf("%ld", nameofDouble); as well but it gave the same result. That is correct right?
Quote:Original post by Elwren
I'm using printf("%d", nameOfDouble);
I tried adding the modifer printf("%ld", nameofDouble); as well but it gave the same result. That is correct right?
No. %d is to print a decimal integer value. You need to use %e, %E, %f, %F, %g, or %G.
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms

This topic is closed to new replies.

Advertisement