我需要在内存中存储一个非常长的数组。每个数组项只是一个标志TRUE / FALSE(0/1)。我需要它非常节省内存,所以我想把它作为unsigned char
区域顶部的掩码位来实现。内存中的每个char
都应该给我至少8个标志。我已经实现了以下功能:
static SIZE = 8; /* 8 bits = 1 byte = 1 char */
/* creates and initializes the array for N elements */
unsigned char *new_bit_array(long n) {
int extra = (n % SIZE) ? 1 : 0;
size_t ms = ((n / SIZE)+extra) * sizeof(unsigned char);
unsigned char *p = malloc(ms);
memset(p,0xFF,ms);
return p;
}
/* mask setter for nth bit of a char, call by function bit_array_set*/
char bit_mask_set(short nbit,short value) {
if (value)
return 0xFF;
if (nbit == 0)
return 0x7F;
else if (nbit == 1)
return 0xBF;
else if (nbit == 2)
return 0xDF;
else if (nbit == 3)
return 0xEF;
else if (nbit == 4)
return 0xF7;
else if (nbit == 5)
return 0xFB;
else if (nbit == 6)
return 0xFD;
else if (nbit == 7)
return 0xFE;
return 0xFF;
}
/* mask setter for nth element of the array */
void bit_array_set(unsigned char *p,long i,int value) {
p[i/] &= bit_mask_set(i % SIZE,value);
}
/* mask getter for nth bit of a char, call by function bit_array_get */
char bit_mask_get(short nbit) {
if (nbit == 0)
return 0x80;
else if (nbit == 1)
return 0x40;
else if (nbit == 2)
return 0x20;
else if (nbit == 3)
return 0x10;
else if (nbit == 4)
return 0x08;
else if (nbit == 5)
return 0x04;
else if (nbit == 6)
return 0x02;
else if (nbit == 7)
return 0x01;
return 0x00;
}
/* mask getter for nth element of the array */
short bit_array_get(unsigned char *p,long i) {
return p[i/SIZE] & bit_mask_get(i % SIZE) ? 1 : 0;
}
这段代码工作正常,但我的问题是,如果C或任何广泛使用的库(即glib)中有任何内置功能可以提供相同的功能吗?
......如果有更好的方法来实现bit_mask_get
和bit_mask_set
,那么7分支IF看起来很难看。对此代码的任何其他评论也非常受欢迎。
答案 0 :(得分:8)
你可以更简单:
unsigned char flag_bitmask[MAX_FLAGS];
void setFlag( int flag) {
flag_bitmask[flag / 8] |= (1 << (flag % 8) );
}
char isFlagSet(int flag) {
return flag_bitmask[flag / 8] & (1 << (flag % 8) );
}
void unSetFlag(int flag) {
flag_bitmask[flag / 8] &= ~(1 << (flag % 8) );
}
我正在使用它,你可以传递flag_bitmask数组而不是将其用作全局数据。
答案 1 :(得分:3)
您可以使用来自SIZE
的宏CHAR_BIT
替换<limits.h>
常量,这会做同样的事情。
在new_bit_array
函数中,您可以用0xFF
替换(unsigned char) ~0
,calloc
不考虑char中的位数。虽然将内存初始化为零位更容易,但可以使用malloc
代替bit_masK_get
。
在return 1 << nbit;
中,您可以使用以下内容替换正文:
bit_mask_set
然后类似地将return (!!value) << nbit;
替换为:
{{1}}
这些位置与您的位置不同,但这并不重要,只要它们在彼此之间保持一致。
答案 2 :(得分:2)
您可以在结构中使用位域。您可以拥有以下结构的数组:
struct bitflags {
unsigned char f0:1;
unsigned char f1:1;
unsigned char f2:1;
unsigned char f3:1;
unsigned char f4:1;
unsigned char f5:1;
unsigned char f6:1;
unsigned char f7:1;
};
struct bitflags many_flags[9001];
many_flags[0].f0 = 1;