Exercise 2-7 of the C programming language:
Write a function invert(x,p,n) that returns x with bits n that start at position p inverted (i.e. 1 is changed to 0 and vice versa), leaving the rest unchanged.
I understood the question as follows: I have 182, which is 101(101)10 in binary format, the part in parentheses should be inverted without changing the rest. The return value should be 10101010 then, which is 170 in decimal value.
Here is my attempt:
#include <stdio.h> unsigned int getbits(unsigned int bitfield, int pos, int num); unsigned int invert(unsigned int bitfield, int pos, int num); int main(void) { printf("%d\n", invert(182, 4, 3)); return 0; } /* getbits: get num bits from position pos */ unsigned int getbits(unsigned int bitfield, int pos, int num) { return (bitfield >> (pos+1-n)) & ~(~0 << num); } /* invert: flip pos-num bits in bitfield */ unsigned int invert(unsigned int bitfield, int pos, int num) { unsigned int mask; unsigned int bits = getbits(bitfield,pos,num); mask = (bits << (num-1)) | ((~bits << (pos+1)) >> num); return bitfield ^ mask; }
Seems right (to me), but invert(182, 4, 3) outputs 536870730 . getbits() works fine (this is straight from the book). I wrote down what happens in the expression that I assigned y :
(00000101 << 2) | ((~00000101 << 5) >> 3) -- 000000101 is the part being flipped: 101(101)10 00010100 | ((11111010 << 5) >> 3) 00010100 | (01000000 >> 3) 00010100 | 00001000 = 00011100 10110110 (182) ^ 00011100 ---------- = 10101010 (170)
It should be right, but it is not. I found out that this is happening incorrectly: ((~xpn << (p+1)) >> n) . I do not see how.
Also, I have no idea how generic this code is. My first priority is simply to make this work. Help in this matter is also welcome.