I'm sure you're interested in actually modifying bits. Once you understand masks, it's easy to modify individual bits.
Here's the prototype of the function we wish to implement.
unsigned char setBit( unsigned char ch, int i ) ;
This will take a character as input, set bi to 1, and return that new character, while leaving the original character untouched (which happens because the original character is passed by value, which means it's a copy of the argument).
Here's the code:
unsigned char setBit( unsigned char ch, int i )
unsigned mask = 1 << i ; // we could cast to unsigned char, just to be safe
return mask | char ; // using bitwise OR
Let's see how this works on an example:
|ch & mask||1||0||0||0||1||0||1||1|
Instead of bitwise AND, we use bitwise OR. If you perform bitwise OR on a bit b with 0, you get back bit b. Thus, for all the bit positions in the mask with zero (in the example above, it's every bit except bit b3 in the mask), the corresponding bit position of ch & mask is just the value of the corresponding bit position in ch.
In other words, whereever there's a 0 in the mask, the original bit value in ch is preserved. For example, b7 = 1 in ch and the mask has a 0 in that position. The result ch & mask also has a 1 at that same bit position.
In fact, the only bit position that can potentially change in the result is the bit position that's a 1 in the mask. The mask has a 1 at b3. When you OR a bit b with 1, you get a 1 as a result.
Thus, this causes b3 to be 1 regardless of what b3 is in ch.
This is exactly the effect we're looking for. Setting b3 to 1 in the result, but leaving all other bits unchanged.