简体   繁体   中英

Integer Byte Swapping in C++

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.

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; x = lobyte << 8 | hibyte;

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 to swap without using any temporary variables:

uint16_t y = ((x & 0xff) << 8) | ((x & 0xff00) >> 8);       

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...

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;
}

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;
}
#include <stdio.h>

int main()
{
   unsigned short a = 258;
   a = (a>>8)|((a&0xff)<<8);
   printf("%d",a);
}

A bit old fashioned, but still a good bit of fun.

XOR swap: ( see How does XOR variable swapping work? )

    #include <iostream>
    #include <stdint.h>
    int main()
    {
        uint16_t x = 0x1234;
        uint8_t *a = reinterpret_cast<uint8_t*>(&x);
        std::cout << std::hex << x << std::endl;
        *(a+0) ^= *(a+1) ^= *(a+0) ^= *(a+1);
        std::cout << std::hex << x << std::endl;
    }

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 char s, and swap the two char s, 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 or d 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.

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;
}

Using library functions, the following code may be useful (in a non-homework context):

unsigned long swap_bytes_with_value_size(unsigned long value, unsigned int value_size) {
    switch (value_size) {
        case sizeof(char):
            return value;

        case sizeof(short):
            return _byteswap_ushort(static_cast<unsigned short>(value));

        case sizeof(int):
            return _byteswap_ulong(value);

        case sizeof(long long):
            return static_cast<unsigned long>(_byteswap_uint64(value));

        default:
            printf("Invalid value size");
            return 0;
    }
}

The byte swapping functions are defined in stdlib.h at least when using the MinGW toolchain.

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 >>.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM