Although the question was closed, but since I was not sure of my old answer. I updated with verified code. Hope it will be useful for someone in the future.
Suppose the bits are numbered from LSB to MSB:
BIT NUMBER 31 0 ▼ ▼ number bits 0000 0000 0000 0000 0000 0000 0001 0101 ▲ ^ ^ ▲ MSB | | LSM | | n=27 m=17 LSB - Least Significant Bit (numbered 0) MSB - Most Significant Bit (numbered 31)
The figure above shows how the bits are numbered from LSB to MSB. Note the relative positions of n and m , where n > m .
Set all bits One from n to m
To set 1 all bits from position m to n (where n > m ) to a 32-bit number. You need a 32-bit mask in which all bits 1 from n to m and the remaining bits are 0 .
For example, to set all the bits from m=17 to n=27 , we need a mask, for example:
BIT NUMBER 31 n=27 m=17 0 ▼ ▼ ▼ ▼ mask = 0000 1111 1111 1110 0000 0000 0000 0000
And if we have a 32-bit number, a bitwise OR ( | ) with this number, we can set 1 all the bits from m to n . And other bits will not be changed.
remember OR works like:
x | 1 = 1 , and x | 0 = x
where x value can be 1 or 0 any.
Thus:
num32bit = num32bit | mask;
we can set n to m bit 1 , and the remaining bits will not be changed. Example, Suppose num32bit = 0011 1001 1000 0000 0111 1001 0010 1101
then:
0011 1001 1000 0000 0111 1001 0010 1101 <--- num32bit 0000 1111 1111 1110 0000 0000 0000 0000 <--- mask ---------------------------------------- ---------------Bitwise OR operation 0011 1111 1111 1110 0111 1001 0010 1101 <--- new number ---- ▲ ▲ ------------------- |-----------| this bits are from `num32bit` all bits are 1 here "This is what I means by": num32bit = num32bit | mask;
How to make a mask?
Make a mask in which all bits 1 from n to m and the others are 0 . we need three steps:
Create mask_n : all bits on the right side of n=27 are equal
BIT NUMBER 31 n=27 0 ▼ ▼ ▼ mask_27= 0000 1111 1111 1111 1111 1111 1111 1111
In programming, this can be created using Right-Shift → 4 times.
And, how 4 came?
4 = 32 - n - 1 ==> 31 - 27 ==> 4
Also note that in the complement ( ~ ) of form 0 all bits are equal to one. and we need an unsigned right shift in C.
Link to find out the difference between a signed and an unsigned right shift
Create mask_m . All bits on the left side of m=17 are equal to one.
BIT NUMBER 31 m=17 0 ▼ ▼ ▼ mask_17 1111 1111 1111 1110 0000 0000 0000 0000
Create mask : Bitwise And higher: mask = mask_n & mask_m :
mask = 0000 1111 1111 1110 0000 0000 0000 0000 ▲ ▲ BIT NUMBER 27 17
And below, my getMask(n, m) function returns an unsigned number that looks like a mask in step 3.
#define BYTE 8 typedef char byte;
To test my getMask (), I also wrote the main () code that uses the binary () function, the binary () function prints the given number in binary formate.
void binary(unsigned); int main(){ unsigned num32bit = 964720941u; unsigned mask = 0u; unsigned rsult32bit; int i = 51; mask = getMask(27, 17); rsult32bit = num32bit | mask; //set n to m bits 1 printf("\nSize of int is = %ld bits, and " "Size of unsigned = %ld eg\n", sizeof(int) * BYTE, sizeof(unsigned) * BYTE); printf("dec= %-4u, bin= ", 21); binary(21); printf("\n\n%s %d\n\t ", "num32bit =", num32bit); binary(num32bit); printf("mask\t "); binary(mask); while(i--) printf("-"); printf("\n\t "); binary(rsult32bit); printf("\n"); return EXIT_SUCCESS; } void binary(unsigned dec){ int i = 0, left = sizeof(unsigned) * BYTE - 1; for(i = 0; left >= 0; left--, i++){ printf("%d", !!(dec & ( 1 << left ))); if(!((i + 1) % 4)) printf(" "); } printf("\n"); }
This test code works like (the output is the same as I explained in the above example):
Output of code: ----------------- $ gcc bc :~$ ./a.out Size of int is = 32 bits, and Size of unsigned = 32 eg dec= 21 , bin= 0000 0000 0000 0000 0000 0000 0001 0101 num32bit = 964720941 0011 1001 1000 0000 0111 1001 0010 1101 mask 0000 1111 1111 1110 0000 0000 0000 0000 --------------------------------------------------- 0011 1111 1111 1110 0111 1001 0010 1101 :~$
Additionally, you can write the getMask () function in shorter form in two operations:
unsigned getMask(unsigned n, unsigned m){ byte noOfBits = sizeof(unsigned) * BYTE; return ((unsigned)~0u >> (noOfBits - n - 1)) & (~0u << (noOfBits -m)); }
Note: I removed the redundant brackets to clear the code. Although you never need to remember the priority of the operators, since you can overwrite the priority using () . But a good programmer always referees to the priority table to write neat code.
And Macro () is best suited, as shown below:
#define BYTE 8 #define _NO_OF_BITS sizeof(unsigned) * BYTE #define MASK(n, m) (((unsigned)~0u >> (_NO_OF_BITS - n - 1)) & \ (~0u << (_NO_OF_BITS - m)))
And call:
rsult32bit = num32bit | MASK(27, 17);
To set all zero bits from n to m
To set all bits from n to m = 0 and reset, you do not need the ( ~ ) mask padding.
mask 0000 1111 1111 1111 1000 0000 0000 0000 ~mask 1111 0000 0000 0000 0111 1111 1111 1111 <-- complement
Also required operator | to set zero & .
Remember And it works like:
x & 0 = 0 , and x & 0 = 0
where x value can be 1 or 0.
Since we already have the bitwise complement operator ~ and the & operator. We just need to do it.
[SOLUTION] :
rsult32bit = num32bit & ~MASK(27, 17);
And it will work as:
num32bit = 964720941 0011 1001 1000 0000 0111 1001 0010 1101 mask 1111 0000 0000 0000 0111 1111 1111 1111 --------------------------------------------------- 0011 0000 0000 0000 0111 1001 0010 1101