In C, I have a 32-bit word representing an address (and I have it stored in an unsigned long, hope that's ok). Now from what I gather, part of an address contains the page number and the other part contains the offset. I was wondering how I could extract just the bits that give me t开发者_运维知识库he page number. I have already worked out the first 22 most significant bits are the page number and the other 10 bits are the page offset. How can I grab just the bits that are the page number? I am thinking I can do this with some bitwise operations, but am not sure how.
Use the bitshift operators to extract the bits you need.
pageNumber = x >> 10;
offset = x & ((1 << 10) - 1);
For the page number, the >> operator shifts bits down, so you lose the least signifcant bits.
For the offset, ((1 << 10) - 1) creates a bitmask consisting of 10 ones which is used to select only the 10 least significant bits and ignore the most significant bits.
I'm a huge fan of the "two shifts" method of field extraction. It works both signed and unsigned. To extract a field of width w
with least significant bit lsb
from word
:
#define BITSIN(W) (8*sizeof(W))
return (word << (BITSIN(word) - (lsb+width))) >> (BITSIN(word) - width);
In this case, BITSIN(word) == 32
and lsb+width == 32
, so as long as the word in question is unsigned, you can just shift right 10 without masking.
One caution: beware 32-bit shifts on 32-bit types! The C standard lets the compiler do anything, and what the common Intel chips do is not useful: x << y
shifts x
left by y % 32
bits (provided x
has a 32-bit integer type). This means if you try to shift a 32-bit integer left or right by 32 bits, the result is the same as a no-op. There is a similar issue with 64-bit shifts of 64-bit types.
精彩评论