如何在 C 中更改 char 数组中位图的单个位?
How can you change a single bit of a bitmap inside a char array in C?
我不得不使用字符数组作为位图。例如,这将是一个 32 位位图:
char bitmap[4];
之前,我已经将这个数组的每个字节都初始化为0。我的问题是,我怎样才能把这个数组的一位改成我想要的呢?我正在寻找一个与此结构类似的函数,其中位图作为参数传递,以及我们要更改的位的索引和我们要将其更改为的值:
set_bit(char *bitmap, int bit, int value);
他们强迫我使用 char 数组而不是 unsigned char 数组。拥有一个具有类似结构的 get_bit 函数也很有用,它只要求位图和要探测的位作为参数。
提前致谢。
编辑:我在 set_bit 定义
中修复了位图的类型
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)
}
或者如果您确定 val
将是 1
或 0
更高效的版本(几个时钟)
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;
}
或更便携的版本(CHAR_BIT 最多 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;
}
我不得不使用字符数组作为位图。例如,这将是一个 32 位位图:
char bitmap[4];
之前,我已经将这个数组的每个字节都初始化为0。我的问题是,我怎样才能把这个数组的一位改成我想要的呢?我正在寻找一个与此结构类似的函数,其中位图作为参数传递,以及我们要更改的位的索引和我们要将其更改为的值:
set_bit(char *bitmap, int bit, int value);
他们强迫我使用 char 数组而不是 unsigned char 数组。拥有一个具有类似结构的 get_bit 函数也很有用,它只要求位图和要探测的位作为参数。
提前致谢。
编辑:我在 set_bit 定义
中修复了位图的类型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)
}
或者如果您确定 val
将是 1
或 0
更高效的版本(几个时钟)
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;
}
或更便携的版本(CHAR_BIT 最多 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;
}