Search code examples
ccharbit-manipulationbit

Bit manipulation inside a char array


I'm writing a function to set/unset bits in an unsigned char array. I've been given the following instructions.

In this task, bit 0 is the most significant bit. It is also assumed that unsigned char is exactly 8 bits (1 byte). Thus, for example, bit 8 is a leftmost bit in second unsigned char byte and bit 17 is the second highest bit in the third unsigned char byte. Thus, examining the number 170 (0xAA hexadecimal format, 10101010 in binary), the most significant bit, ie bit 0 has a value of 1.

based on that, I wrote the following.

/* NOTE:
 * -----------
 * The parameter binary data (const unsigned char*) in all the functions 
 * below is likely to hold more than 8 bits. You should take this into 
 * account when implementing your functions.
 */

/* DESCRIPTION:
 * ------------
 * The function sets a bit with index i as active (1) in the parameter
 * binary data.
 *
 * PARAMETERS:
 * ------------
 * unsigned char* data: an array of binary data.
 * int i: the index of the bit which to set as active (1).
 *
 * RETURNS:
 * ------------
 * Nothing.
 *
 */
void op_bit_set(unsigned char *data, int i)
{
    data[i/32] |= 1 << (i%32); 
}

/* DESCRIPTION:
 * ------------
 * The function sets a bit with index i as inactive (0) in the parameter
 * binary data.
 *
 * PARAMETERS:
 * ------------
 * unsigned char* data: an array of binary data.
 * int i: the index of the bit which to set as active (1).
 *
 * RETURNS:
 * ------------
 * Nothing.
 *
 */

void op_bit_unset(unsigned char *data, int i)
{
     data[i/32] &= ~(1 << (i%32)); 
}

When I test it with the given data, my answer is wrong.

unsigned char arr[2] = {0, 0};
 op_bit_set(arr, 0);

 *** Testing your op_bit_set function.. 
 At first arr[0] == 0x00 and arr[1] == 0x00 
 Setting bit 0 arr[0] is 0x01, should be 0x80 
 arr[1] is 0x00, should be 0x00

I based my answer on what I read here: http://www.mathcs.emory.edu/~cheung/Courses/255/Syllabus/1-C-intro/bit-array.html


Solution

  • As Thomas mentioned, you are using an unsigned char which has 8 bits. So your logic for determining the index and the bit number should use 8 instead of 32.

    Also, since the most significant bit is the left most bit, you have to shift right 0x80(or 128) by i which gives you a mask for the specific bit that you want to set/unset.

    In the end the code should look like this.

    void op_bit_set(unsigned char *data, int i)
    {
        data[i/8] |= 0x80 >> (i%8); 
    }
    
    void op_bit_unset(unsigned char *data, int i)
    {
         data[i/8] &= ~(0x80 >> (i%8)); 
    }