5

I'm trying to do the following:

Write a func setbits(x,p.n,y) that returns x with n bits that begin at position p set to the rightmost n bits of y,leaving the other bits unchanged?

I tried it like this but not getting correct answers. Can anyone tell where I am wrong?

unsigned setbits(unsigned x,int p,int n,unsigned y)
{
    return (x>>p & (y|(~0<<n)));
}
user1413523
  • 345
  • 1
  • 7
  • 15
  • 1
    First of all, when you're writing bitwise C, it's a great idea to use temporary variables with helpful names to help you see what you're doing. The compiler will probably optimize them all out anyway, but the source code legibility will remain. – Misha Jul 21 '12 at 08:19
  • i have edited the function to take x a s parameter. – user1413523 Jul 21 '12 at 08:21
  • x is currently a 1-bit wide variable, and shifting it for any p will effectively zero it out. – Misha Jul 21 '12 at 08:22
  • 6
    Homework? Is it? – Ed Heal Jul 21 '12 at 08:22
  • @Mike: x is an unsigned integer (32 bits i am taking) so shifting it by p will cause to set upper p bits of x to 0.Correct me if i am wrong? – user1413523 Jul 21 '12 at 08:24
  • 1
    @Ed Heal: Its not HW rather i am learning bitwise operations in c and i came across this question in a book.I tried but not sure with my method and get wrong result.So i asked for help. – user1413523 Jul 21 '12 at 08:26
  • What is the book and author - just out of idle curiosity? – Ed Heal Jul 21 '12 at 08:33
  • Read my answer here: [To Set all bits One from n to m](http://stackoverflow.com/questions/15917454/set-the-m-bit-to-n-bit/15918195#15918195) – Grijesh Chauhan Jul 14 '13 at 21:03

4 Answers4

3

Something like:

unsigned setbits(unsigned x,int p,int n,unsigned y)
{
    unsigned mask = (1U << n) - 1U; // n-bits
    y &= mask; // rightmost n bits of y
    y <<= p;   // which begin at position p
    mask <<= p; //idem
    x &= ~mask; //set the 0s
    x |= y;     //set the 1s
    return x;
}

Or if you want to do it in fewer lines, more difficult to debug, but waaaay cooler:

unsigned setbits(unsigned x,int p,int n,unsigned y)
{
    unsigned mask = (1U << n) - 1U; // n-bits
    return (x & ~(mask << p)) | ((y & mask) << p);
}
rodrigo
  • 94,151
  • 12
  • 143
  • 190
1

Kernighan and Ritchie, 2nd edition, exercise 2-6. The solution is from http://users.powernet.co.uk/eton/kandr2/krx206.html :

(x & ((~0 << (p + 1)) | (~(~0 << (p + 1 - n))))) | ((y & ~(~0 << n)) << (p + 1 - n))

Oleg2718281828
  • 1,039
  • 7
  • 17
1

Catching the last n bits of y: (will be a number with the last n bits equal to y, and the others set to zero)

last_n_bits_of_y = y & (((1<<(n+1))-1);

then we can offset it by (32-n-p+1) (check this!)

last_n_bits_of_y_offset = last_n_bits_of_y << (32-n-p+1);

now we erase the bits of x we want to change:

new_x = x & (~( (((1<<(n+1))-1) << (32-n-p+1) ) );

and populate it with our bits:

new_x = new_x & last_n_bits_of_y_offset;

That's it! Didn't really test it, but hopefully, you'll get the idea.

Márcio Paiva
  • 983
  • 9
  • 25
1
  1. You x>>() so you loose x rightmost bits and then never restore them later in you function.
  2. One can not set bits using only & because the result depends on both operands unless you know one of them consists only of 1
  3. (y|(~0<<n)) is supposed to cut bits from y but it's not, this time | is not the right tool, use & and appropriate second operand.

Here is the solution(I bet there is shorter one, but this is straight-forward):

(x & ~(~(~0<<n)<<p) | (y&~(~0<<n)) << p);

Left part of | clears the place in x(n bits at position p) and the right part brings y bits.

nshy
  • 1,074
  • 8
  • 13