aoeu
aoeu

Reputation: 154

Trouble Understanding How to Set Bits

For an assignment in my systems class, we are learning how bit manipulation works and I'm having trouble implementing it into this function:

void setting_bits(int value, int pos, int n) {
    int n_val = value;
    
    printf("\nsetting_bits(0x%X, %i, %i) -> ",value,pos,n);
    
    int mask = 1;
    mask = (mask << n)-pos-1;
    n_val = n_val & ~mask;
    printf("0x%X",n_val);
    printf("\n");
}

Here is an example input output:

setting_bits(0xA1B2C3D4, 1, 4) -> 0xA1B2C3DE

I just don't understand how to go about the logic. I think I understand the basics like how the bits can be modified and how masking works but I'm not sure how to put it all together. My class forums didn't prove useful nor does my professor respond to emails so I'm here for last resort. Anything response will be appreciated. I don't want to end up hating hexadecimal for the rest of my career.

Upvotes: 0

Views: 90

Answers (1)

Dmitri
Dmitri

Reputation: 9375

Here's a rewrite of the function:

void setting_bits(unsigned value, int pos, int n) {
    printf("\nsetting_bits(0x%X, %i, %i) -> ",value,pos,n);

    unsigned n_val = value | ((1u << n) - 1) << pos;
    
    printf("0x%X\n", n_val);
}

...to set n consecutive bits starting at bit position pos in value and display the result.

The key part here is value | ((1u << n) - 1) << pos.

(1u << n) gets us one bit set followed by n zero bits. We then subtract 1 from that, which gives us n set bits instead. Then we shift all that left by pos to get it into the correct position. Finally, we bitwise OR it with the old value which gives us value, but with all those bits set if they weren't already.

An example using 8 bits in binary, with value of 0101 0101, n of 3, and pos of 2:

(1u << n)                       -->   00000001b << 3        --> 00001000b
((1u << n) - 1)                 -->   00001000b - 1         --> 00000111b
((1u << n) - 1) << pos          -->   00000111b << 2        --> 00011100b
value | ((1u << n) - 1) << pos  -->   01010101b | 00011100b --> 01011101b

Upvotes: 3

Related Questions