Convert Signed Big Endian short to Little Endian signed Short

I have a file that contains signed shorts in big-endian format.

How do I convert these to little-endian SIGNED format?

I thought I had this working, but later realized I didn't handle negative values.

Thanks
oxygen_728Asked:
Who is Participating?
 
rajeev_devinCommented:
A technique

union BYTES {
   unsigned short number;
   unsigned char bytes[2];
};

BYTES b;
read(&b.bytes[1], 1, ...); // Read first byte in index 1
read(&b.bytes[0], 1, ...); // Read first byte in index 0

b.number contains the number in little-endian.
0
 
rajeev_devinCommented:
Just interchange the bytes
0
 
e_tadeuCommented:
It is much more efficient if you read them in a batch and use the swab function!
E.g:

#include <cstdlib>
#include <cstdio>

using namespace std;

short inputArray[1024], array[1024];
fread(inputArray, sizeof short, 1024, someFile);

// now swap the bytes
swab(reinterpret_cast<char*>(inputArray), reinterpret_cast<char*>(array), sizeof inputArray);

Or, if you would like to do it without the extra memory buffer, but with a speed penalty, you can do it 'inplace', like this:

inline inswab(char *array, size_t bytes) {
  for (int i = 0; i < bytes; i += 2) {
    register char aux = array[i];
    array[i] = array[i+1];
    array[i+1] = aux;
  }
}

See:
http://www.cplusplus.com/ref/cstdlib/swab.html
http://www.codeproject.com/cpp/endianness.asp
0
Cloud Class® Course: SQL Server Core 2016

This course will introduce you to SQL Server Core 2016, as well as teach you about SSMS, data tools, installation, server configuration, using Management Studio, and writing and executing queries.

 
rstaveleyCommented:
If your application is running on a little-endian system, you can use ntohs and htons to convert to and from the host (little-endian) from and to network (big-endian) byte order. See http://www.google.com/search?q=htons
0
 
oxygen_728Author Commented:
raj:

Are you sure it is as simple as interchanging the bytes? There's a sign bit in there somewhere.
I switched over from unsigned shorts to signed shorts and my results are screwy with the numbers that should be negative
0
 
oxygen_728Author Commented:
E_Tadeu:

well, that doesnt seem far from what I'm doing:

      ifstream in;
      in.open("N36W117.hgt",ios::in | ios::binary);
      int x;
      short Val = 0;
      int counter = 0;
      Vertices = new SimpleVertex[1201*1201];
   
      //load in elevation data
      while (counter < 1201 * 1201){
            in.read((char*)&Val, 2);                      //<--------------------------------------------------
            Val = (Val << 8) | (Val >> 8);             //<----------------------------------------------------
            Vertices[counter].x = counter % 1201;
            Vertices[counter].y = Val;
            Vertices[counter].z = counter / 1201;
            counter++;
      }
0
 
oxygen_728Author Commented:
I think I found part of the problem;

short Val;
Val = 0xa300

Val = Val >> 8;

Val will equal ffa3 instead of  00a3

Must be a sign issue.

0
 
oxygen_728Author Commented:
Ya, apparently I was using a short too early - there was some funky stuff going on with the bit shifting.

Val >> 8   SOMETIMES would fill in the 'new' bits (on the left) with f's instead of 0's  (hex)

It's all fixed now, I used bytes - and I learned about this strange union structure thanks to rajeev.

Thanks guys
0
 
Infinity08Commented:
>> Val >> 8   SOMETIMES would fill in the 'new' bits (on the left) with f's instead of 0's  (hex)
that "SOMETIMES" happens when the left most bit is set to 1 ... by shifting, you shift in that same bit on the left side. That doesn't happen with unsigned integer types though.

The rule with converting between little and big endian is to either use unsigned types, or to avoid shifting when using signed types.

Any way you inter-change bytes would be ok ... and I see you already have some examples given by the others :)
0
 
e_tadeuCommented:
Note: if you use "unsigned short", the problem of filling 1's in the left should not happen. It only happens with signed shift, because of negative numbers in 2's-complement!
0
 
oxygen_728Author Commented:
Perhaps I could have used unsigned shorts, then performed a cast to a signed short? I have a feeling that conversion does something goofy to overcome the negativity though =\
0
 
Infinity08Commented:
Can I ask why you need to extract certain bits from a signed short ? It sounds like it's something that could be done easier differently.
0
 
rstaveleyCommented:
> Val >> 8   SOMETIMES would fill in the 'new' bits (on the left) with f's instead of 0's  (hex)

The problem occurred when you made the original assignment, which set the signed bit.

--------8<--------
#include <stdio.h>

int main()
{
      short Val;
      Val = 0xa300;   // Same as assigning -23808 to the short
      printf("%hd %hx %x\n", Val, Val, Val);

      Val = Val >> 8;
      printf("%hd %hx %x\n", Val, Val, Val);
}
--------8<--------

The shift right operator drags the signed bit into the most significant bit, when you operate on signed integers.
0
 
oxygen_728Author Commented:
Well, I'm just reading in data in big-endian signed-short format... and I need the data in little-endian signed-short format.
0
 
oxygen_728Author Commented:
rstavlely - I thought I had read somewhere that 0's are always 'dragged in' ... I don't remember reading anything about the sign bit being dragged in - thus my confusion =)

Thanks for clearing things up!
0
 
Infinity08Commented:
>> Well, I'm just reading in data in big-endian signed-short format... and I need the data in little-endian signed-short format.
My apologies - I mixed up two questions ... ignore my question :)

>> I thought I had read somewhere that 0's are always 'dragged in'
That's true for unsigned types
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.