LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   C function to reverse the byte order in a double? (https://www.linuxquestions.org/questions/programming-9/c-function-to-reverse-the-byte-order-in-a-double-825743/)

sneakyimp 08-12-2010 04:41 AM

C function to reverse the byte order in a double?
 
I'm trying to write an extension to PHP which means coding in C. I'm really really rusty at C coding and was never very good at it.

Can anyone propose an efficient, safe, and [hopefully] future-proof way of reversing a double? Keep in mind that it should work on as many systems as possible and on 32- and 64-bit systems (and on ???-bit systems in the future?). Will the size of a 'double' ever change or will it always be 8 bytes?

I've tried this and it doesn't work...the compiler complains about "invalid operands to binary" because I'm trying bitwise shiftw on a non-integer.
Code:

    x = (x>>56) |
        ((x<<40) & 0x00FF000000000000) |
        ((x<<24) & 0x0000FF0000000000) |
        ((x<<8)  & 0x000000FF00000000) |
        ((x>>8)  & 0x00000000FF000000) |
        ((x>>24) & 0x0000000000FF0000) |
        ((x>>40) & 0x000000000000FF00) |
        (x<<56);

Any advice would be much appreciated.

Sergei Steshenko 08-12-2010 05:16 AM

Quote:

Originally Posted by sneakyimp (Post 4063889)
... I'm trying bitwise shiftw on a non-integer. ...

There is type casting, as well as there are unions.

I.e. either case you double to long enough (unsigned) int or use a union whose one field will be your double and the other - long enough (unsigned) int.

dwhitney67 08-12-2010 08:29 AM

Quote:

Originally Posted by Sergei Steshenko (Post 4063919)
There is type casting, as well as there are unions.

I.e. either case you double to long enough (unsigned) int or use a union whose one field will be your double and the other - long enough (unsigned) int.

I agree. I nicked the following code for a previous project I supported; it supposedly is used to convert 64-bit values to Network-Byte-Order values, similar to using htons() or htonl() for short and long values.

Maybe the OP can use it:
Code:

#include <stdint.h>
#include <stdio.h>

uint64_t ntohll(const uint64_t value)
{
  enum { TYP_INIT, TYP_SMLE, TYP_BIGE };

  union
  {
      uint64_t ull;
      uint8_t  c[8];
  } x;

  // Test if on Big Endian system.
  static int typ = TYP_INIT;

  if (typ == TYP_INIT)
  {
      x.ull = 0x01;
      typ = (x.c[7] == 0x01) ? TYP_BIGE : TYP_SMLE;
  }

  // System is Big Endian; return value as is.
  if (typ == TYP_BIGE)
  {
      return value;
  }

  // else convert value to Big Endian
  x.ull = value;

  int8_t c = 0;
  c = x.c[0]; x.c[0] = x.c[7]; x.c[7] = c;
  c = x.c[1]; x.c[1] = x.c[6]; x.c[6] = c;
  c = x.c[2]; x.c[2] = x.c[5]; x.c[5] = c;
  c = x.c[3]; x.c[3] = x.c[4]; x.c[4] = c;

  return x.ull;
}

uint64_t htonll(const uint64_t value)
{
  return ntohll(value);
}


int main(void)
{
  double value = 3.1456;

  // display bytes (of original value)
  unsigned char* cptr = (unsigned char*) &value;
  for (int i = 0; i < sizeof(double); ++i)
  {
      printf("%3d ", cptr[i]);
  }
  printf("\n");

  // convert value to Network-Byte-Order.
  uint64_t nbo = ntohll(*((uint64_t*) &value));

  // display bytes (of result)
  cptr = (unsigned char*) &nbo;
  for (int i = 0; i < sizeof(double); ++i)
  {
      printf("%3d ", cptr[i]);
  }
  printf("\n");

  return 0;
}


Sergei Steshenko 08-12-2010 11:24 AM

Well, entering

convert double to network order

into Yahoo yields as the very first match: http://www.dmh2000.com/cpp/dswap.shtml .


All times are GMT -5. The time now is 06:21 AM.