alestarbucks
alestarbucks

Reputation: 119

How can you change a single bit of a bitmap inside a char array in C?

I'm forced to use a char array as a bitmap. For instance, this would be a 32-bit bitmap:

char bitmap[4];

Beforehand, I have initialized every single byte of this array to 0. My question is, how can I change a single bit of this array to be the one I want? I'm looking for a function with a similar structure to this, where the bitmap is passed as a parameter, along with the index of the bit we want to change and the value we want to change it to:

set_bit(char *bitmap, int bit, int value);

They force me to use a char array instead of an unsigned char array. It would also be useful to have a get_bit function with a similar structure that only asks for the bitmap and the bit to be probed as arguments.

Thank you in advance.

EDIT: I fixed the type of the bitmap in the set_bit definition

Upvotes: 0

Views: 667

Answers (1)

0___________
0___________

Reputation: 67574

void setbit(void *arr, size_t bit, unsigned val)
{
    unsigned char *ucarr = arr;     // void * to prevent compiler warnings when you pass other type pointer. 
    size_t index = bit >> 3;        //>>3 is == divide by 8 which is number of bits in char on most systems. Index number
    unsigned char mask = 1 << (bit & 7);  // &7 - bit number in the 8 bits charackter

    ucarr[index] &= ~mask;               // zero the bit
    ucarr[index] |= mask * (!!val);      // set the bit to the value (1 of var nonzero, 0 if var == 0) 

}

or if you are sure that val will be 1 or 0 a bit more efficient version (few clocks)

void setbit1(void *arr, size_t bit, unsigned val)
{
    unsigned char *ucarr = arr;
    size_t index = bit >> 3;
    size_t bitindex = bit & 7;
    unsigned char mask = 1 << bitindex;

    ucarr[index] &= ~mask;
    ucarr[index] |= val << bitindex; 
}

or a bit more portable version (CHAR_BIT up to 256)

#define CHO     (((CHAR_BIT >> 1) & 1)*2 + ((CHAR_BIT >> 2) & 1)*4 + ((CHAR_BIT >> 3) & 1)*8 + ((CHAR_BIT >> 4) & 1)*16 + ((CHAR_BIT >> 5) & 1)*32 + ((CHAR_BIT >> 6) & 1)*64 + ((CHAR_BIT >> 7) & 1)*128 + ((CHAR_BIT >> 8) & 1)*256)

void setbit(void *arr, size_t bit, unsigned val)
{
    unsigned char *ucarr = arr;
    size_t index = bit >> CHO;
    unsigned char mask = 1 << (bit & (CHAR_BIT - 1));

    ucarr[index] &= ~mask;
    ucarr[index] |= mask * (!!val); 
}

void setbit1(void *arr, size_t bit, unsigned val)
{
    unsigned char *ucarr = arr;
    size_t index = bit >> CHO;
    size_t bitindex = bit & (CHAR_BIT - 1);
    unsigned char mask = 1 << bitindex;

    ucarr[index] &= ~mask;
    ucarr[index] |= val << bitindex; 
}

Upvotes: 2

Related Questions