views:

145

answers:

3

Hi I'm been looking around how to convert big endian to little endians. But I didn't find any good that could solve my problem. It seem to be there's many way you can do this conversion. Anyway this following code works ok in a big endian system. But how should I write a conversion function so it will work on little endian system as well?

This is a homework, but it just an extra since the systems at school running big endian system. It's just that I got curious and wanted to make it work on my home computer also

#include <iostream>
#include <fstream>

using namespace std;

int main()
{
   ifstream file;

   file.open("file.bin", ios::in | ios::binary);

   if(!file)
      cerr << "Not able to read" << endl;
   else
   {
      cout << "Opened" << endl;

      int i_var;
      double d_var;

      while(!file.eof())
      {
         file.read( reinterpret_cast<char*>(&i_var) , sizeof(int) );
         file.read( reinterpret_cast<char*>(&d_var) , sizeof(double) );
         cout << i_var << " " << d_var << endl;
      }
   }
   return 0;
}

Solved

So Big endian VS Little endian is just a reverse order of the bytes. This function i wrote seem to serve my purpose anyway. I added it here incase someone else would need it in future. This is for double only though, for it either use the function torak suggested or you can modify this code by making it to swap 4 bytes only.

double swap(double d)
{
   double a;
   unsigned char *dst = (unsigned char *)&a;
   unsigned char *src = (unsigned char *)&d;

   dst[0] = src[7];
   dst[1] = src[6];
   dst[2] = src[5];
   dst[3] = src[4];
   dst[4] = src[3];
   dst[5] = src[2];
   dst[6] = src[1];
   dst[7] = src[0];

   return a;
}
+1  A: 

Assuming you're going to be going on, it's handy to keep a little library file of helper functions. 2 of those functions should be endian swaps for 4 byte values, and 2 byte values. For some solid examples (including code) check out this article.

Once you've got your swap functions, any time you read in a value in the wrong endian, call the appropriate swap function. Sometimes a stumbling point for people here is that single byte values do not need to be endian swapped, so if you're reading in something like a character stream that represents a string of letters from a file, that should be good to go. It's only when you're reading in a value this is multiple bytes (like an integer value) that you have to swap them.

Bryan
actually i get confused since there's alot of different swap. On that article it was swaps for short, long and float. Will any of those swaps work for the datatypes i'm working with?
starcorn
The solutions are dependent on the size of your data value. If you have a 2 byte value, you use `ShortSwap()`, if you have a 4 byte value `LongSwap().` The `FloatSwap()` in the example there is kind of pointless, except in that there's a logical difference between float storage and long storage... The LongSwap will still work correctly on a 4 byte float though. What you did in your posted solution up top is effectively the same thing for an 8 byte value.
Bryan
+3  A: 

You might be interested in the ntohl family of functions. These are designed to transform data from network to host byte order. Network byte order is big endian, therefore on big endian systems they don't do anything, while the same code compiled on a little endian system will perform the appropriate byte swaps.

torak
is there's something similar for double?
starcorn
The way that floating point numbers are represented is more complicated (and varried) than for itegers, and I've never tried so I'm not 100% sure. However, assuming that the floating point representations on the two machines match (except for endianness) the article that Bryan linked to suggests it should be possible.
torak
+2  A: 

You could use a template for your endian swap that will be generalized for the data types:

#include <algorithm>

template <class T>
void endswap(T *objp)
{
  unsigned char *memp = reinterpret_cast<unsigned char*>(objp);
  std::reverse(memp, memp + sizeof(T));
}

Then your code would end up looking something like:

file.read( reinterpret_cast<char*>(&i_var) , sizeof(int) );
endswap( &i_var );
file.read( reinterpret_cast<char*>(&d_var) , sizeof(double) );  
endswap( &d_var );
cout << i_var << " " << d_var << endl;  
Dingo
I have something similar, but taking the object per reference, instead of pointer.
sbi