czar x
czar x

Reputation: 448

Swap byte 2 and 4 in a 32 bit integer

I had this interview question -

Swap byte 2 and byte 4 within an integer sequence. Integer is a 4 byte wide i.e. 32 bits

My approach was to use char *pointer and a temp char to swap the bytes. For clarity I have broken the steps otherwise an character array can be considered.

unsigned char *b2, *b4, tmpc;
int n = 0xABCD; ///expected output 0xADCB
b2 = &n;   b2++;  
b4 = &n;   b4 +=3;
///swap the values;
tmpc = *b2;
*b2 = *b4;
*b4 = tmpc;

Any other methods?

Upvotes: 4

Views: 18563

Answers (3)

Hot Licks
Hot Licks

Reputation: 47729

int someInt = 0x12345678;

int byte2 = someInt & 0x00FF0000;
int byte4 = someInt & 0x000000FF;
int newInt = (someInt & 0xFF00FF00) | (byte2 >> 16) | (byte4 << 16);

To avoid any concerns about sign extension:

int someInt = 0x12345678;
int newInt = (someInt & 0xFF00FF00) | ((someInt >> 16) & 0x000000FF) | ((someInt << 16) & 0x00FF0000);

(Or, to really impress them, you could use the triple XOR technique.)

Just for fun (probably a tupo somewhere):

int newInt = someInt ^ ((someInt >> 16) & 0x000000FF);
newInt = newInt ^ ((newInt << 16) & 0x00FF0000);
newInt = newInt ^ ((newInt >> 16) & 0x000000FF);

(Actually, I just tested it and it works!)

Upvotes: 7

Emil Sit
Emil Sit

Reputation: 23542

You can mask out the bytes you want and shift them around. Something like this:

unsigned int swap(unsigned int n) {
  unsigned int b2 = (0x0000FF00 & n);
  unsigned int b4 = (0xFF000000 & n);
  n ^= b2 | b4;                 // Clear the second and fourth bytes
  n |= (b2 << 16) | (b4 >> 16); // Swap and write them.
  return n;
}

This assumes that the "first" byte is the lowest order byte (even if in memory it may be stored big-endian).

Also it uses unsigned ints everywhere to avoid right shifting introducing extra 1s due to sign extension.

Upvotes: 4

yeyo
yeyo

Reputation: 3009

What about unions?

int main(void)
{
    char  tmp;
    union {int n; char ary[4]; } un;

    un.n = 0xABCDEF00;
    tmp = un.ary[3];
    un.ary[3] = un.ary[1];
    un.ary[1] = tmp;
    printf("0x%.2X\n", un.n);
}

in > 0xABCDEF00

out>0xEFCDAB00

Please don't forget to check endianess. this only work for little endian, but should not be hard to make it portable.

Upvotes: 2

Related Questions