my solution
get the rightmost n bits of y
a = ~(~0 << n) & y
clean the n bits 开发者_JS百科of x beginning from p
c = ( ~0 << p | ~(~0 << (p-n+1))) & x
set the cleaned n bits to the n rightmost bits of y
c | (a << (p-n+1))
it is rather long statements. do we have a better one?
i.e
x = 0 1 1 1 0 1 1 0 1 1 1 0
p = 4
y = 0 1 0 1 1 0 1 0 1 0
n = 3
the 3 rightmost bits of y is 0 1 0
it will replace x from bits 4 to bits 2 which is 1 1 1
I wrote similar one:
unsigned setbits (unsigned x, int p, int n, unsigned y)
{
return (x & ~(~(~0<<n)<<(p+1-n)))|((y & ~(~0<<n))<<(p+1-n));
}
There are two reasonable approaches.
One is yours: Grab the low n bits of y
, nuke the middle n
bits of x, and "or" them into place.
The other is to build the answer from three parts: Low bits "or" middle bits "or" high bits.
I think I actually like your version better, because I bet n
and p
are more likely to be compile-time constants than x
and y
. So your answer becomes two masking operations with constants and one "or"; I doubt you will do better.
I might modify it slightly to make it easier to read:
mask = (~0 << p | ~(~0 << (p-n+1)))
result = (mask & a) | (~mask & (y << (p-n+1)))
...but this is the same speed (indeed, code) as yours when mask
is a constant, and quite possibly slower when mask
is a variable.
Finally, make sure you have a good reason to worry about this in the first place. Clean code is good, but for something this short, put it in a well-documented function and it does not matter that much. Fast code is good, but do not attempt to micro-optimize something like this until your profiler tells you do. (Modern CPUs do this stuff very fast; it is unlikely your application's performance is bounded by this sort of function. At the very least it is "innocent until proven guilty".)
Have a look at the following descriptive code:
int setbitsKR(int x, int p, int n, int y){
int shiftingDistance = p - n + 1,
bitmask = (1 << n) - 1, // example, 11
digitsOfY = (y & bitmask) << shiftingDistance, // whatever
bitmaskShiftedToLeft = bitmask << shiftingDistance, // 001100
invertedBitmaskShiftedToLeft = ~bitmaskShiftedToLeft; // 110011
// erase those middle bits of x
x &= invertedBitmaskShiftedToLeft;
// add those bits from y into x
x |= digitsOfY;
return x;
}
In short, it creates a bitmask (string of 1
s), shifts them to get to that middle position of x
, nukes those bits of x
by &
ing with a string of 0
s (inverted bitmask), and finally |
s that position with the right digits of y
.
精彩评论