我有一个 unsigned char 缓冲区,我想知道如何向这个字节缓冲区写入和读取有符号和无符号位。
在 Source Engine 中有一个名为 bf_write 的类,其中两个主要方法(由WriteString,WriteChar,WriteLong等使用)使用两个名为 WriteUBitLong 和 WriteSBitLong 。
提前致谢
答案 0 :(得分:10)
如果位数是编译时常量:
#include <bitset>
...
std::bitset<100> b;
b[2]=true;
如果不是,请使用Boost.dynamic_bitset
或者,如果你是绝望的,std :: vector,这确实是一个打包的位向量:
#include <vector>
...
std::vector<bool> b(100);
b[2]=true;
您似乎想要使用需要以字节数组形式打包的位向量的库。如果不确切知道它的位置是什么,我只能注意到:
1)以上所有内容都可能使用至少32位整数,其中位数最少 - >大多数或大多数 - >最不重要
2)在小端(Intel / AMD)CPU上,这意味着由一个int数组的字节占用的内存可能与int内的位排序不一致。如果它是“位0是int 0的lsb,...位32是int 1的lsb,...”那么小端的相同,因为“位0是char 0的lsb,...位32是char 4的lsb ...“,在这种情况下,您可以将指向int数组的指针强制转换为指向char数组的指针
3)假设您的位集/向量中的本地字节顺序不是库所需的,那么您必须创建自己具有所需布局的自定义,或者将副本转录到其布局中。
a)如果一个字节内的位顺序不同,那么给出具有反转位的字节的256条目查找表将是有效的。你可以用一个小例程生成表格。
b)从little&lt; - &gt; big endian反转字节:
inline void endian_swap(unsigned short& x)
{
x = (x>>8) |
(x<<8);
}
inline void endian_swap(unsigned int& x)
{
x = (x>>24) |
((x<<8) & 0x00FF0000) |
((x>>8) & 0x0000FF00) |
(x<<24);
}
inline void endian_swap(unsigned long long& x)
{
x = (x>>56) |
((x<<40) & 0x00FF000000000000) |
((x<<24) & 0x0000FF0000000000) |
((x<<8) & 0x000000FF00000000) |
((x>>8) & 0x00000000FF000000) |
((x>>24) & 0x0000000000FF0000) |
((x>>40) & 0x000000000000FF00) |
(x<<56);
}
要获取/设置字中的特定位,在字0的最低有效位中使用位#0:
typedef unsigned char block_t;
const unsigned block_bits=8;
inline void set_bit(block_t *d,unsigned i) {
unsigned b=i/block_bits;
unsigned bit=i-(block_bits*b); // same as i%b
block_t &bl=d[b];
bl|=(1<<bit); // or bit with 1 (others anded w/ 0)
}
inline void clear_bit(block_t *d,unsigned i) {
unsigned b=i/block_bits;
unsigned bit=i-(block_bits*b); // same as i%b
block_t &bl=d[b];
bl&=(~(1<<bit)); // and bit with 0 (other bits anded w/ 1)
}
inline void modify_bit(block_t *d,unsigned i,bool val) {
if (val) set_bit(d,i) else clear_bit(d,i);
}
inline bool get_bit(block_t const* d,unsigned i) {
unsigned b=i/block_bits;
unsigned bit=i-(block_bits*b); // same as i%b
return d[b]&(1<<bit);
}
显然,如果位组织规则不同,则必须更改上述内容。
尽可能使用尽可能广泛的CPU进程,因为block_t是最好的(不要忘记更改block_bits
),除非使用您正在使用的库时字节顺序无效。
答案 1 :(得分:1)
我认为一些宏就足够了:
#define set_bit0(buf, i) ((buf)[(i)/8]&=~(1u<<(i)%8))
#define set_bit1(buf, i) ((buf)[(i)/8]|=1<<(i)%8)
#define get_bit(buf, i) ((buf)[(i)/8]>>(i)%8&1)
此外,交换字节顺序可以更快的方式完成。例如,对于64位整数v,以下操作交换其字节顺序:
v = ((v & 0x00000000FFFFFFFFLLU) << 32) | (v >> 32);
v = ((v & 0x0000FFFF0000FFFFLLU) << 16) | ((v & 0xFFFF0000FFFF0000LLU) >> 16);
v = ((v & 0x00FF00FF00FF00FFLLU) << 8) | ((v & 0xFF00FF00FF00FF00LLU) >> 8);