views:

193

answers:

9

I'm working on a homework assignment for my C++ class. The question I am working on reads as follows:

Write a function that takes an unsigned short int (2 bytes) and swaps the bytes. For example, if the x = 258 ( 00000001 00000010 ) after the swap, x will be 513 ( 00000010 00000001 ).

Here is my code so far:

#include <iostream>

using namespace std;

unsigned short int ByteSwap(unsigned short int *x);

int main()
{
  unsigned short int x = 258;
  ByteSwap(&x);

  cout << endl << x << endl;

  system("pause");
  return 0;
}

and

unsigned short int ByteSwap(unsigned short int *x)
{
  long s;
  long byte1[8], byte2[8];

  for (int i = 0; i < 16; i++)
  {
    s = (*x >> i)%2;

    if(i < 8)
    {
      byte1[i] = s;
      cout << byte1[i];
    }
    if(i == 8)
      cout << " ";

    if(i >= 8)
    {
      byte2[i-8] = s;
      cout << byte2[i];
    }
  }

  //Here I need to swap the two bytes
  return *x;
}   

My code has two problems I am hoping you can help me solve.

  1. For some reason both of my bytes are 01000000
  2. I really am not sure how I would swap the bytes. My teachers notes on bit manipulation are very broken and hard to follow and do not make much sense me.

Thank you very much in advance. I truly appreciate you helping me.

+1  A: 

While you can do this with bit manipulation, you can also do without, if you prefer. Either way, you shouldn't need any loops though. To do it without bit manipulation, you'd view the short as an array of two chars, and swap the two chars, in roughly the same way as you would swap two items while (for example) sorting an array.

To do it with bit manipulation, the swapped version is basically the lower byte shifted left 8 bits ord with the upper half shifted left 8 bits. You'll probably want to treat it as an unsigned type though, to ensure the upper half doesn't get filled with one bits when you do the right shift.

Jerry Coffin
So without bit manipulation are you talking about typecasting the short into a char and breaking it in half? I dont have much experience with this but I think it would be interesting to try.
Rob S.
@Rob S.: You'd typically take its address, and cast that to pointer to char, or you could use a union of the two types (`short` and `char [2]`). Absent a reason to do otherwise, I'd probably use the pointer.
Jerry Coffin
+7  A: 

I think you're overcomplicating it, if we assume a short consists of 2 bytes (16 bits), all you need to do is

  • extract the high byte hibyte = (x & 0xff00) >> 8;
  • extract the low byte lobyte = (x & 0xff);
  • combine them in the reverse order x = lobyte << 8 | hibyte;
nos
I'm not familiar with that syntax. Can you provide me a reference to it please?
Rob S.
Brian
+3  A: 

You're making hard work of that.

You only neeed exchange the bytes. So work out how to extract the two byte values, then how to re-assemble them the other way around

(homework so no full answer given)

EDIT: Not sure why I bothered :) Usefulness of an answer to a homework question is measured by how much the OP (and maybe other readers) learn, which isn't maximized by giving the answer to the homewortk question directly...

Paul
Can you provide me with any reference or reading material on this? I believe most of my problem is that I lack a lot of background knowledge on this subject.
Rob S.
@Rob S. : One way to do this is with a `union`. See my answer for an example. Another way to do this is by ugly pointer casting. E.g. `short s = 258; unsigned char tmp = (*(unsigned char *)( There is probably a better way.
Brian
@RobS if you're really taking a C++ class there must be class materials for that. If the class isn't providing them, find a different class! You're asking some very basic questions and shouldn't need pointers to answers (e.g. meaning of << etc)
Paul
Paul, my teacher barely speaks comprehensible English and gives me the impression he doesnt understand the subject very well himself. I did not purchase his class textbook because he listed it as being only 'recommended' and not 'required' and it was nearly 200 USD. I have been doing most of my learning on the Internet and through deciphering his notes. Lastly, I was more interested in | and )
Rob S.
Fair enough - it just looked a little like you were looking to be spoonfed answers. Sounds like you could do with buying one of the popular (and not $200!) books on C++...
Paul
+2  A: 

It looks like you are trying to swap them a single bit at a time. That's a bit... crazy. What you need to do is isolate the 2 bytes and then just do some shifting. Let's break it down:

uint16_t x = 258;

uint16_t hi = (x & 0xff00); // isolate the upper byte with the AND operator

uint16_t lo = (x & 0xff); // isolate the lower byte with the AND operator

Now you just need to recombine them in the opposite order:

uint16_t y = (lo << 8); // shift the lower byte to the high position and assign it to y
y |= (hi >> 8);         // OR in the upper half, into the low position

Of course this can be done in less steps. For example:

uint16_t y = (lo << 8) | hi >> 8);

Or without any temporaries:

uint16_t y = ((x & 0xff) << 8) | x & 0xff00) >> 8);
Evan Teran
+1 nice, seems like everyone can type answers much faster and better than I can :D
KennyCason
Rob S.
Those are the AND and OR logical bitwise operators in C. http://en.wikipedia.org/wiki/Bitwise_operation
Evan Teran
Thank you very much once again :)
Rob S.
A: 

This is a problem:

byte2[i-8] = s;
cout << byte2[i];//<--should be i-8 as well

This is causing a buffer overrun.

However, that's not a great way to do it. Look into the bit shift operators << and >>.

Skizz
A: 

This should also work for you.

#include <iostream>

int main() {
    unsigned int i = 0xCCFF;
    std::cout << std::hex << i << std::endl;

    i  = ( ((i<<8) & 0xFFFF) | ((i >>8) & 0xFFFF)); // swaps the bytes

    std::cout << std::hex << i << std::endl;
}
KennyCason
A: 
#include <stdio.h>


int main()
{
   unsigned short a = 258;

   a = (a>>8)|((a&0xff)<<8);

   printf("%d",a);


}
siri
+1  A: 

Ugly implementation of Jerry's suggestion to treat the short as an array of two bytes:

#include <iostream>
typedef union mini
{
    unsigned char b[2];
    short s;
} micro;
int main()
{
    micro x;
    x.s = 258;
    unsigned char tmp = x.b[0];
    x.b[0] = x.b[1];
    x.b[1] = tmp;
    std::cout << x.s << std::endl;
}
Brian
Thank you very much for this. This helps me a lot :)
Rob S.
+1  A: 

Here is an unrolled example to demonstrate byte by byte:

unsigned int swap_bytes(unsigned int original_value)
{
  unsigned int new_value = 0; // Start with a known value.
  unsigned int byte;          // Temporary variable.

  // Copy the lowest order byte from the original to
  // the new value:
  byte = original_value & 0xFF;  // Keep only the lowest byte from original value.
  new_value = new_value * 0x100; // Shift one byte left to make room for a new byte.
  new_value |= byte;             // Put the byte, from original, into new value.

  // For the next byte, shift the original value by one byte
  // and repeat the process:
  original_value = original_value >> 8; // 8 bits per byte.
  byte = original_value & 0xFF;  // Keep only the lowest byte from original value.
  new_value = new_value * 0x100; // Shift one byte left to make room for a new byte.
  new_value |= byte;             // Put the byte, from original, into new value.

  //...
  return new_value;
}
Thomas Matthews
nice commenting
KennyCason