0

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?

13
  • 4
    Looks like a Brainfck program... Commented Sep 20, 2017 at 18:31
  • stackoverflow.com/questions/10493411/what-is-bit-masking Commented Sep 20, 2017 at 18:32
  • I would lay out the code in a more readable manner. In its current state it might as well be a PPCG answer. Commented Sep 20, 2017 at 18:33
  • c is an uninitialised variable so the operation will be undefined behaviour. Please post the typical Minimal, Complete, and Verifiable example that shows the code. Commented Sep 20, 2017 at 18:46
  • 1
    @Groo I deleted my answer which does that, because that is not the problem spec. Commented Sep 20, 2017 at 19:00

3 Answers 3

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

Sign up to request clarification or add additional context in comments.

Comments

0

"Better" as in: "Beauty is in the eye of the beholder."?

Simply? another way: (uses "no"!? operations other than assignment?)

The 1988 2nd edition of "The C Programming Language" by Kernighan and Ritchie in the last two sections of Chapter 6 explains the subtleties and idiosyncrasies of this code:

uint8_t c; uint8_t string[3]; union { uint8_t bits; struct { uint8_t t7 :1; uint8_t t3456 :4; uint8_t t2 :1; uint8_t t1 :1; uint8_t t0 :1; } bi; struct { uint8_t b7 :1; uint8_t b6 :1; uint8_t b2345 :4; uint8_t b1 :1; uint8_t b0 :1; } ti; } b,d; b.bits = d.bits = c; // does b.ti.b1 = d.bi.t1; b.ti.b7 = d.bi.t7; b.ti.b0 = d.bi.t2; b.ti.b2345 = d.bi.t3456; b.ti.b6 = d.bi.t0; string[2] = b.bits; 

Problems? Read the book and consider:

 struct { uint8_t t0 :1; uint8_t t1 :1; uint8_t t2 :1; uint8_t t3456 :4; uint8_t t7 :1; } bi; struct { uint8_t b0 :1; uint8_t b1 :1; uint8_t b2345 :4; uint8_t b6 :1; uint8_t b7 :1; } ti; 

Comments

0

if your memory were big, you can use your function to generate a lookup array of length=256 in compile time. when you do the rearrange job in run time, just look it up in the array. this can boost your speed up into 1 clockcycle in best case.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.