1

I have a double converted to a unsigned char array. For example for value 1, the array becomes {64, 240, 0, 0, 0, 0, 0, 0}. Now I tried to convert the array back by using the following code, but all I got was crapy values...

double* pdfOutput = (double*)malloc(sizeof(double));
memcpy(pdfOutput, pInputArray, sizeof(double));

Would you please let me know where the problem is? Thanks.

Edit: The pInputArray is generated by LabVIEW. Basically what I am trying to do here is to make a program talking with a LabVIEW VI. So I don't have the control of the input array...

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
will2km
  • 57
  • 1
  • 5
  • 4
    Hint: you can use `double x; memcpy(&x, ...` and not bother with dynamic memory allocation. – R. Martinho Fernandes Mar 21 '12 at 20:17
  • 1
    Can you show the other routine, that goes the other way? And how is `pInputArray` defined? And what is an unsigned signed char? – Mr Lister Mar 21 '12 at 20:18
  • 1
    C++ or C? They're not always the same. – Carl Norum Mar 21 '12 at 20:22
  • Just learned about this site today, you may find it useful: http://babbage.cs.qc.cuny.edu/IEEE-754.old/64bit.html It says your array isn't 1.0 but 65536.0. – Mark Ransom Mar 21 '12 at 20:22
  • The pInputArray is generated by LabVIEW. Basically what I am trying to do here is to make a program talking with a LabVIEW VI. So I don't have the control of the input array... – will2km Mar 21 '12 at 20:23
  • 1
    I tried converting from double to unsigned char array and got {63 240 0 0 0 0 0 0}, not the same as you got. Converting this back to double gives 1. Maybe there is a mistake somewhere in your conversion to unsigned char. I double-checked with two compilers. – Israel Unterman Mar 21 '12 at 20:25
  • I know noticed your comment about the auto generated array. Try replace 63 for 64. If it works then it could be a problem in the auto conversion. – Israel Unterman Mar 21 '12 at 20:32
  • What is the code in LabVIEW to generate the pInputArray? Have you typecasted a double to a string? If you want to control the endianess (I guess that's tricking you since LabVIEW is big-endian) you'd better use 'flatten to string' that let's you select the endianess – Ton Plomp Mar 22 '12 at 18:49

2 Answers2

5

The simple way to do what you ask is to write:

double pdfOutput = *(double*)pInputArray;

but this will yield just the same results as your code. In other words, reinterpreting the char array that you have does not result in the double value that you expect. You need to look into the source of the char array. The code that is creating the char array is where I would expect the problem to be. To solve your problem you need to understand what the LabVIEW code is doing.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
1

The problem is the order of the bytes (i.e. endianness). You may not be able to simply use memcpy(), depending on the endianness of your system. Regardless, if you're dealing with individual bytes, you'll have to take endianness into account... what will work on one system will not necessarily work on another.

Try this program:

#include <stdio.h>

//typedef __int64            int64;  // for Visual Studio
//typedef unsigned __int64   uint64; // for Visual Studio
typedef long long          int64;  // for GCC
typedef unsigned long long uint64; // for GCC

//#define PRId64 "%I64d" // for Visual Studio
//#define PRIu64 "%I64u" // for Visual Studio
#define PRIu64 "%llu"  // for GCC
#define PRId64 "%lld"  // for GCC

union U {
  unsigned char c[8];
  int64  s64;
  uint64 u64;
  double d;
};

void printU( U& u )
{
printf("Raw bytes:  %02x %02x %02x %02x %02x %02x %02x %02x "
        " (%u %u %u %u %u %u %u %u)\n"
        "Interpreted as a    signed 64-bit integer: "PRId64"\n"
        "Interpreted as an unsigned 64-bit integer: "PRIu64"\n"
        "Interpreted as a double (with 'float' precision): %f\n\n",
        u.c[0], u.c[1], u.c[2], u.c[3],
        u.c[4], u.c[5], u.c[6], u.c[7],
        u.c[0], u.c[1], u.c[2], u.c[3],
        u.c[4], u.c[5], u.c[6], u.c[7],
        u.s64, u.u64, (float)u.d);
}

int main()
{
  U u;

  u.c[0]=63;   u.c[1]=240;  u.c[2]=0;   u.c[3]=0;
  u.c[4]=0;    u.c[5]=0;    u.c[6]=0;   u.c[7]=0;
  printU(u);

  u.c[0]=0;    u.c[1]=0;    u.c[2]=0;   u.c[3]=0;
  u.c[4]=0;    u.c[5]=0;    u.c[6]=240; u.c[7]=63;
  printU(u);
}

On my x86 Linux system with GCC, I get the following results:

Raw bytes:  3f f0 00 00 00 00 00 00  (63 240 0 0 0 0 0 0)
Interpreted as a    signed 64-bit integer: 61503
Interpreted as an unsigned 64-bit integer: 61503
Interpreted as a double (with 'float' precision): 0.000000

Raw bytes:  00 00 00 00 00 00 f0 3f  (0 0 0 0 0 0 240 63)
Interpreted as a    signed 64-bit integer: 4607182418800017408
Interpreted as an unsigned 64-bit integer: 4607182418800017408
Interpreted as a double (with 'float' precision): 1.000000

I suspect someone running Visual Studio (on x86 of course) would get the same results. When I run the same program on a PowerPC Linux machine (also GCC), I get these results:

Raw bytes:  3f f0 00 00 00 00 00 00  (63 240 0 0 0 0 0 0)
Interpreted as a    signed 64-bit integer: 4607182418800017408
Interpreted as an unsigned 64-bit integer: 4607182418800017408
Interpreted as a double (with 'float' precision): 1.000000

Raw bytes:  00 00 00 00 00 00 f0 3f  (0 0 0 0 0 0 240 63)
Interpreted as a    signed 64-bit integer: 61503
Interpreted as an unsigned 64-bit integer: 61503
Interpreted as a double (with 'float' precision): 0.000000

I'm making the assumption that you can convert this research into the appropriate conversion code for your platform. If my assumption is incorrect, let me know & I'll write the 2-line code you need for you after you run the above program on your system & post the results.

phonetagger
  • 7,701
  • 3
  • 31
  • 55