【发布时间】:2010-11-16 14:16:38
【问题描述】:
位图是array of bits。它是如何在 C 中实现的?
【问题讨论】:
位图是array of bits。它是如何在 C 中实现的?
【问题讨论】:
我假设您问的是如何在 C 中实现位图(或位数组)。令人惊讶的是,维基百科上的 Bit_array 条目描述了这个概念,但实际上并没有显示如何来实现基本操作,就这样吧。
简而言之,创建一个您最喜欢的无符号类型的数组,并进行正确的算术运算来决定如何设置/清除其中的位。
#include <limits.h> /* for CHAR_BIT */
#include <stdint.h> /* for uint32_t */
typedef uint32_t word_t;
enum { BITS_PER_WORD = sizeof(word_t) * CHAR_BIT };
#define WORD_OFFSET(b) ((b) / BITS_PER_WORD)
#define BIT_OFFSET(b) ((b) % BITS_PER_WORD)
void set_bit(word_t *words, int n) {
words[WORD_OFFSET(n)] |= (1 << BIT_OFFSET(n));
}
void clear_bit(word_t *words, int n) {
words[WORD_OFFSET(n)] &= ~(1 << BIT_OFFSET(n));
}
int get_bit(word_t *words, int n) {
word_t bit = words[WORD_OFFSET(n)] & (1 << BIT_OFFSET(n));
return bit != 0;
}
【讨论】:
1 是一个有符号的常规 int,这会引发两个问题:它不能保证是 32 位,而 1 << 31 是未定义的行为(因为符号位)。上述代码中的所有文字 1s 应替换为无符号的 32 位 (word_t) 1。
你可以使用“位域”。
$ cat src/bitmap.c
#include <stdio.h>
#define BITS 4
struct BITMAP {
unsigned value : 1;
} bit[BITS];
int main(){
bit[0].value = 0;
bit[1].value = 1;
// implicit truncation from 'int' to bit-field changes value from 2 to 0 [-Wbit/field-constant-conversion]
bit[2].value = 2;
bit[3].value = 3;
int i;
for ( i=0; i < BITS ; i++){
printf("Value of bit %i is %u\n", i, bit[i].value);
}
}
结果
$ gcc src/bitmap.c -lm -o bitmap && ./bitmap
src/bitmap.c: In function ‘main’:
src/bitmap.c:14:24: warning: unsigned conversion from ‘int’ to ‘unsigned char:1’ changes value from ‘2’ to ‘0’ [-Woverflow]
14 | bit[2].value = 2;
| ^
src/bitmap.c:15:24: warning: unsigned conversion from ‘int’ to ‘unsigned char:1’ changes value from ‘3’ to ‘1’ [-Woverflow]
15 | bit[3].value = 3;
| ^
Value of bit 0 is 0
Value of bit 1 is 1
Value of bit 2 is 0
Value of bit 3 is 1
【讨论】:
struct BITMAP 的实际大小将大于 1 位,因为它必须对齐 -- 如果 sizeof(unsigned) 是 4 个字节,那么 sizeof(struct BITMAP) 也是 4 个字节。