Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swap two bits with a single operation in C?

Let's say I have a byte with six unknown values:

???1?0??

and I want to swap bits 2 and 4 (without changing any of the ? values):

???0?1??

But how would I do this in one operation in C?

I'm performing this operation thousands of times per second on a microcontroller so performance is the top priority.

It would be fine to "toggle" these bits. Even though this is not the same as swapping the bits, toggling would work fine for my purposes.

like image 542
Nate Murray Avatar asked Jun 11 '09 14:06

Nate Murray


People also ask

How do you swap two bits in a number?

Method 1: The idea is to first find the bits, then use XOR based swapping concept, i..e., to swap two numbers 'x' and 'y', we do x = x ^ y, y = y ^ x, and x = x ^ y.

What is nibble swap in C?

To swap the nibbles, we can use bitwise &, bitwise ” operators. A byte can be represented using a unsigned char in C as size of char is 1 byte in a typical C compiler. Below is the implementation of above idea.

How do I change adjacent bits?

Given an integer, swap adjacent bits of it. In other words, swap bits present at even positions with those present in odd positions. The idea is to separate bits present at even positions with bits present at odd positions using mask 0xAAAAAAAA and 0x55555555 , respectively.

Which operator is used to reverse the bits?

Bitwise complement operator is used to reverse the bits of an expression.


2 Answers

Try:

x ^= 0x14;

That toggles both bits. It's a little bit unclear in question as you first mention swap and then give a toggle example. Anyway, to swap the bits:

x = precomputed_lookup [x];

where precomputed_lookup is a 256 byte array, could be the fastest way, it depends on the memory speed relative to the processor speed. Otherwise, it's:

x = (x & ~0x14) | ((x & 0x10) >> 2) | ((x & 0x04) << 2);

EDIT: Some more information about toggling bits.

When you xor (^) two integer values together, the xor is performed at the bit level, like this:

for each (bit in value 1 and value 2)
   result bit = value 1 bit xor value 2 bit

so that bit 0 of the first value is xor'ed with bit 0 of the second value, bit 1 with bit 1 and so on. The xor operation doesn't affect the other bits in the value. In effect, it's a parallel bit xor on many bits.

Looking at the truth table for xor, you will see that xor'ing a bit with the value '1' effectively toggles the bit.

 a  b a^b
 0  0  0
 0  1  1
 1  0  1
 1  1  0

So, to toggle bits 1 and 3, write a binary number with a one where you want the bit to toggle and a zero where you want to leave the value unchanged:

00001010

convert to hex: 0x0a. You can toggle as many bits as you want:

0x39 = 00111001

will toggle bits 0, 3, 4 and 5

like image 184
Skizz Avatar answered Sep 21 '22 00:09

Skizz


You cannot "swap" two bits (i.e. the bits change places, not value) in a single instruction using bit-fiddling.

The optimum approach if you want to really swap them is probably a lookup table. This holds true for many 'awkward' transformations.

BYTE lookup[256] = {/* left this to your imagination */};

for (/*all my data values */) 
  newValue = lookup[oldValue];
like image 25
Roddy Avatar answered Sep 23 '22 00:09

Roddy