在 8K 字节的内存空间内,如何存 unsigned short 类型数据?
一般做法:
定义一个数组: unsigned short arrNormal[4096];
这样做,最多只能存 4K 个 unsigned short 数据。
利用位图法:
定义一个数组: unsigned char arrBit[8192];
这样做,能存 8K*8=64K 个 unsigned short 数据。
写数据元素:计算待写入数据在 arrBit 存放的字节位置和位位置(字节 0~8191 ,位 0~7 )
比如写 1234 ,字节序: 1234/8 = 154; 位序: 1234 & 0b111 = 2 ,那么 1234 放在 arrBit 的下标 154 字节处,把该字节的 2 号位( 0~7 )置为 1
字节位置: int nBytePos = 1234/8 = 154;
位位置: int nBitPos = 1234 & 7 = 2;
// 把数组的 154 字节的 2 位置为 1
unsigned short val = 1<<nBitPos;
arrBit[nBytePos] = arrBit[nBytePos] | val; // 写入 1234 得到 arrBit[154]=0b00000100
此时再写入 1236 ,
字节位置: int nBytePos = 1236/8 = 154;
位位置: int nBitPos = 1236 & 7 = 4
// / 把数组的 154 字节的 4 位置为 1
val = 1<<nBitPos;
arrBit[nBytePos] = arrBit[nBytePos] | val; // 再写入 1236 得到 arrBit[154]=0b00010100
读数据元素:按位读取 arrBit ,取得位为 1 的字节位置和位位置。元素值为 8* nBytePos + nBitPos
for (i=0; i<8192; i++)
{
for (j=0; j<8; j++)
{
if (arrBit[i] & (1<<j))
{
cout << "arrBit:" << i << " " << j << " " << 8*i+j << endl;
}
}
}
会输出:
arrBit:154 2 1234
arrBit:154 4 1236
删除元素:计算待删除元素的字节位置和位位置: arrBit[nBytePos] &= ~(1<< nBitPos);
比如删除 1234 : arrBit[154] &= ~(1<<2);
位图法的缺点:
1. 可读性差
2. 位图存储的元素个数虽然比一般做法多,但是存储的元素大小受限于存储空间的大小。
位图存储性质:存储的元素个数等于元素的最大值。
比如, 1K 字节内存,能存储 8K 个值大小上限为 8K 的元素。(元素值上限为 8K ,这个局限性很大!)
比如,要存储值为 65535 的数,就必须要 65535/8=8K 字节的内存。要就导致了位图法根本不适合存 unsigned int 类型的数(大约需要 2^32/8=5 亿字节的内存)。
3. 位图对有符号类型数据的存储,需要 2 位来表示一个有符号元素。这会让位图能存储的元素个数,元素值大小上限减半。
比如 8K 字节内存空间存储 short 类型数据只能存 8K*4=32K 个,元素值大小范围为 -32K~32K 。
综上所诉:位图法的适用范围很特殊。