Andrew W
Andrew W

Reputation: 9

Masking bits within a range given in parameter in C

I am new to C programming and not sure that there is already a good explanation for how to do this, if so I am sorry. I am trying to set the bits within a range given to me. the function signature looks like:

unsigned int setBits(int low, int high, unsigned int source) {

source being the number to be operated on, low being the lowest bit in the range, and high being the highest bit in the range. I understand bit-shifting just fine when trying to get specifically the last 4 bits or first 4 or any combination thereof, but do not understand how to get the bits from a range that will be changed in the parameter. Any help would be greatly appreciated.

Upvotes: 1

Views: 3466

Answers (4)

Andrew W
Andrew W

Reputation: 9

This was my solution: The if statements at the front just cover conditionals about low and high. This is passing all the tests I was given.

unsigned int setBits(int low, int high, unsigned int source)
 {
 if (low < 0)         {return source;}
 else if (high > 31)  {return source;}
 else if (low > high) {return source;}
 else {
         unsigned int mask = 0xFFFFFFFF << (31 - high);
         mask = mask >> ((31 - high) + low);
         mask = mask << low;
         return source | mask;
     }        

}

Upvotes: -1

luser droog
luser droog

Reputation: 19504

Here are some simple examples of shifting and creating masks to motivate the more general expression.

1             == 00001b
1<<2          == 00100b
(1<<2)-1      == 00011b
((1<<2)-1)<<2 == 01100b

So,

((1<<(high-low+1))-1)<<low

Upvotes: 1

chux
chux

Reputation: 153498

2 approaches: Iterative method to set bit in source from low to high:

unsigned int setBitsI(int low, int high, unsigned int source) {
  while (low <= high) {
    source |= 1u << low;
    low++;
  }
  return source;
}

Non-iterative method:

unsigned int setBitsNI(int low, int high, unsigned int source) {
  unsigned setmask = 1u << (high - low);
  setmask <<= 1;
  setmask--;
  setmask <<= low;
  return source | setmask;
}

Important to avoid 1u << (1u + high - low) for when high is "bit-width-1" and low is 0, 1u << bit_width is UB.

Should low or high have an value outside the bit range, problems occur.

Upvotes: 3

SandBag_1996
SandBag_1996

Reputation: 1601

If its inclusive

mask = ~(~0 << (end - start + 1));
value = (n >> start) & mask;

where n is the original integer, and value is the extracted bits.

Upvotes: 3

Related Questions