Reputation: 9
I'm attempting to shift a 16 bit address to get a set ID for a cache simulator in C, but when I try and bit shift right I get an extra 1 stuck onto my number.
I have the number 0010100010011001. I then shift to the left 3 digits to get 0100010011001000. So far so good. However, I then try to shift to the right 6 digits and end up with 0000010100010011 instead of 0000000100010011. All of my ints are unsigned, and it only adds one 1 when I try and shift.
My code to try and shift is the following. In my example, tag_size is 3 and b is 6.
unsigned int temp = addr << tag_size;
unsigned int temp1 = temp >> b;
unsigned int setid = temp1 >> tag_size;
Upvotes: 0
Views: 434
Reputation: 41180
You should use a mask and select the bits you are interested in; for example:
unsigned int temp = (addr << tag_size) & 0xffffu; // keep 16 low bits
unsigned int temp1 = temp >> b;
unsigned int setid = temp1 >> tag_size;
If I understand what you are after, the same thing can be accomplished with
unsigned int temp = addr & (0xffffu >> tag_size); // keep 16 low bits
unsigned int setid = temp >> b;
or
unsigned int temp = (addr << tag_size) & 0xffffu; // keep 16 low bits
unsigned int setid = temp >> (b + tag_size);
This makes the code independent of unsigned int
size, which C guarantees is at least 16 bits.
Upvotes: 0
Reputation: 386
16 bit int
s are not common these day. You could try defining the variable as a short
which is commonly 16 bits. It all depends on the machine you are using. You could also use a uint16
if you are looking for a 16 bit integer.
It looks like the problem could be because the unsigned int
you are using is not actually 16 bits as Christian Gibbons mentioned in a comment. When you shift 0010100010011001
to the left 3 digits you end up with 10100010011001000
, with the left most 1 not being removed as you would expect in a 16 bit integer then when you shift right again you get the added 1 you were not expecting.
You could change your code to this and it should work as you originally expected:
uint16_t temp = addr << tag_size;
uint16_t temp1 = temp >> b;
uint16_t setid = temp1 >> tag_size;
Upvotes: 1