问题
0000 => 0000
0001 => 1111
0010 => 1110
0100 => 1100
1000 => 1000
Also:
0101 => 1101
As you can see I need to fill with '1's after the last '1', but I do not know in advance where the last '1' is.
回答1:
Maybe something like
unsigned int data;
unsigned int copy = data;
unsigned int shifts = 0;
while (copy > 0) {copy=copy>>1; ++shifts;};
data = data|((1<<shifts)-1);
回答2:
Instead of directly making the mask of the bits that have to be switched on, it's easier to make the mask of bits that should be unchanged (not really, but it's easier to explain this way): copy the left-most 1 to all bits to the right of it:
m = x | (x >> 1);
m |= m >> 2;
m |= m >> 4;
m |= m >> 8;
m |= m >> 16; // 5 steps for 32 bits, in general log2(width) steps
For example, 0101 => 0111, or 1000 -> 1111.
Clearly the complement of that is the mask of bits that should be turned on (unless x was zero), so now:
if (x != 0) // this line makes me sad :(
x |= ~m;
Avoids a long loop, but still has a part in it that isn't strictly bit-manipulation.
Less clearly, using the trick from my comment, observe that if m only had its left most 1 set, its negation would be the bits that have to be set in x (and a bit that is already set in x, but that's ok). So you get:
m &= ~(m >> 1); // see below
x |= -m;
The m &= ~(m >> 1) trick takes only the leftmost 1 of m, this is possible now because m is a power of two minus 1, so the only 1 that can have a 0 to the left of it is the leftmost 1. In the case of x = 0, m = 0 and therefore obviously m & something = 0 - no special case required. In the case that x has the top bit set and thus m = -1, while there is no zero to the left of the leftmost 1, it gets shifted in by the right shift anyway (make sure it's a logical shift, not an arithmetic shift).
来源:https://stackoverflow.com/questions/25689315/how-to-do-the-bit-manipulation-when-you-dont-know-where-the-left-most-1-bit-i