cbit-shift

How to rearrange bits?


I have to rearagne bits in a byte. I solved the problme like this:

uint8_t c;
uint8_t string[3];

string1[2] = (((c&(1<<0))!=0)<<6)|
             (((c&(1<<1))!=0)<<1)|
             (((c&(1<<2))!=0)<<0)|
             (((c&(1<<3))!=0)<<2)|
             (((c&(1<<4))!=0)<<3)|
             (((c&(1<<5))!=0)<<4)|
             (((c&(1<<6))!=0)<<5)|
             (((c&(1<<7))!=0)<<7);

basicly:

if bit0 is a 1, shift a 1 6times to the left.

if bit1 is a 1, shift a 1 0times to the left. ....

Is there a better solution?


Solution

  • (((c&(1<<x))!=0)<<y)
    

    can also be written as

    ((c&(1<<x)))<<(y-x))
    

    Right off the bat, that eliminates one operation per bit. (Keep in mind that y-x is constant.)

    But that's not it. If you apply this transformation throughout, you'll notice that some bits are shifted by the same amount.

    (( c & 0x01 ) << 6 ) |
    (( c & 0x02 )      ) |
    (( c & 0x04 ) >> 2 ) |
    (( c & 0x08 ) >> 1 ) |
    (( c & 0x10 ) >> 1 ) |
    (( c & 0x20 ) >> 1 ) |
    (( c & 0x40 ) >> 1 ) |
    (( c & 0x80 )      )
    

    We can group those.

    (( c & 0x01 ) << 6 ) |
    (( c & 0x82 )      ) |
    (( c & 0x78 ) >> 1 ) |
    (( c & 0x04 ) >> 2 )
    

    We reduced 30 operations down to 10.