本文主要讲述用C语言数组实现二进制位的几种操作。
所谓的位数组,主要是为了有效地利用内存空间而设计的一种存储数据的方式。在这种结构中一个整数在内存中用一位(1 bit)表示。这里所谓的表示就是如果整数存在,相应的二进制位就为1,否则为0。
主要思想:我们知道一个 char 类型的数据在内存中占用 1Byte(即 8 bit),如果我们用二进制位在内存中的顺序来代表整数则可以存储更多的信息。
这样的话,一个 char 类型可以存储 8个整数。即 第1个二进制位代表整数0,第二个二进制位代表整数1,以此类推。
那更大的整数如何表示呢?
我们可以用 char数组 来解决这个问题。假设 a是一个 char 数组的话,整数8就可以用 a[1] 的第一个二进制位表示了。
这里的关键就是 一个char型能表示8个整数。
下面我实现一种利用 char 数组实现的二进制数组。主要包括以下三个方法:
(1)将一个整数添加到二进制数组中 add_to_bitarray(char *, int)
该方法的主要作用是将二进制数组中表示该整数的位置为1。首先我们得找到该整数位于 char 数组的第几个元组中,这里利用该整数除以8即可(代码中除以8用右移三位实现),例如整数25位于25/8 = 3 余 1,表明该整数是用char 数组的第三个元组的第二位表示,在该元组的第几位可以利用该整数的后三位表示,即 25 & 0x7 = 1。将相应位置为1.可以先将整数1左移相应位数,然后与二进制数组进行或操作即可。(详细实现见代码)
(2)判断一个整数是否在二进制数组中 is_in_bitarray(char *, int)
先找到该整数在二进制数组中的位置,然后判断该位是否为1,若是则表示该整数位于二进制数组中,反之不在数组中。
(3)删除二进制数组中的一个整数 clear_bitarray(char *, int)
思路相同,先找到该整数在二进制数组中的位置,然后将该位置为0即可。(如何确定位置通方法(1),具体实现见代码)。
/****************************************************
* author: yym from XMU.
* function: using bitwise logical operations
* (such as and,or and shift) to implement bit vectors
****************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SHIFT 3
#define MASK 0x7
char *init_bitarray(int);
void add_to_bitarray(char *, int);
int is_in_bitarray(char *, int);
void clear_bitarray(char *, int);
void test(char *);
int main(){
char *arr;
arr = init_bitarray(100);
add_to_bitarray(arr, 90);
test(arr);
clear_bitarray(arr, 90);
test(arr);
return 0;
}
char *init_bitarray(int size){
char *tmp;
tmp = (char*)malloc(size / 8 + 1);
memset(tmp, 0, (size / 8 + 1)); //initial to 0
return tmp;
}
void add_to_bitarray(char *bitarr, int num){
bitarr[num >> SHIFT] |= (1 << (num & MASK));
}
int is_in_bitarray(char *bitarr, int num){
return bitarr[num >> SHIFT] & (1 << (num & MASK));
}
void clear_bitarray(char *bitarr, int num){
bitarr[num >> SHIFT] &= ~(1 << (num & MASK));
}
void test(char *bitarr){
if(is_in_bitarray(bitarr, 30) != 0)
printf("30 in\n");
else
printf("30 not in\n");
if(is_in_bitarray(bitarr, 90) != 0)
printf("90 in\n");
else
printf("90 not in\n");
}