2

Possible Duplicate:
Explanation of an algorithm to set, clear and test a single bit

I have an unsigned char. I would like to have bits 2 through 4 (counting from the least significant bit as 0) copied to another unsigned char as the first three bits. For example, in

abcdefgh // a,b,c,d,e,f,g,h are 0 or 1

becomes

00000def

I have tried

unsigned char input, output;
output = (input << 3) >> 5;

which does not work, but

output = (input << 3)
output >>= 5;

does work.

Is there a way in C to accomplish this in one line?

Community
  • 1
  • 1
cubetwo1729
  • 1,438
  • 1
  • 11
  • 18
  • 1
    There are **sooo** many duplicates of this question. The one I linked to above is the special case of wanting a single bit, but it generalises easily. – Oliver Charlesworth Jan 02 '12 at 23:18
  • It doesn't work because `input << 3` is an `int`, not an `unsigned char`. `output = (unsigned char)(input << 3) >> 5;` works. – pmg Jan 02 '12 at 23:19
  • @pmg or `output = ((unsigned int) input << 3) >> 5;` so the two the bitwise shifts will be done on unsigned operands. – ouah Jan 02 '12 at 23:26
  • @ouah: no --- the problem is that `int` (and `unsigned int`) has more than 8 bits it can extend left into. – pmg Jan 02 '12 at 23:33

3 Answers3

8

shift it, then mask the rest off:

output = ( input >> 2 ) & 0x07;
rsaxvc
  • 1,675
  • 13
  • 20
2

This gets only the bits you want then shifts them to the right. It's the opposite approach of @rsaxvc.

output = (input & 28) >> 2;
Marlon
  • 19,924
  • 12
  • 70
  • 101
0

Try this:

unsigned char input, output;
input = 0x12abcdef;
output = ((input & 0x00fff000) >> 3) & 0x00000fff;

I don't think you can just shift back and forth on the same line and assume every time you shift the space is filled by zeroes, but this may be compiler dependent, if you do this you'll get the right thing guaranteed.

I'm assuming by "first three bits" you mean the 3 least significant bits, which is the leftmost or first 3 bits on little-endian systems.

Ian
  • 4,169
  • 3
  • 37
  • 62
  • The compiler abstracts this bit-endianness away. LSB is on the right, MSB on the left, even on middle-byte-endian hardware. By the way, you're overflowing your 'input'. – rsaxvc Jan 10 '12 at 02:01
  • This optimizes to: output=0; input is an 8bit uchar, and when masked with 0x00fff000 becomes 0. >>3 still zero. &0x00000fff still zero. – rsaxvc Jan 10 '12 at 02:03