我想创建一个数组,它的每个单元格在 C++ 中只有 2 位。有什么办法吗?
有一些创建位数组的方法,但它们只为每个单元分配一位。
如果你想从头开始写这个:
可能所有位集实现使用的基本思想是拥有一个int[]
(或实际上任何其他整数类型),并使用按位操作来获取或设置特定位。
我相信您可以在网上找到大量的开源实现,其中一个例子是 Java 的BitSet(可在此处获得)。您可能也可以在bitset
某个地方找到 C++。
同样的想法也适用于这里——不是将某个索引映射到一位,而是将其映射到两位。
如果您可以使用标准库类:
这是我快速整理的内容。
我写了一个twoBitSet
扩展类std::bitset
,它本质上是一个位数组;然后它将一些提供的索引映射到bitset
.
还有一个twoBit
辅助类 - 使用[]
运算符修改数据而不使用它有些困难。
#include <iostream>
#include <bitset>
template <size_t N>
class twoBit
{
typedef typename std::bitset<2*N>::reference bitRef;
bitRef a, b;
public:
twoBit(bitRef a1, bitRef b1): a(a1), b(b1) {};
const twoBit &operator=(int i) { a = i%2; b = i/2; return *this; };
operator int() { return 2*b + a; };
};
template <size_t N>
class twoBitSet : private std::bitset<2*N>
{
typedef typename std::bitset<2*N>::reference bitRef;
public:
twoBit<N> operator[](int index)
{
bitRef b1 = std::bitset<2*N>::operator[](2*index);
bitRef b2 = std::bitset<2*N>::operator[](2*index + 1);
return twoBit<N>(b1, b2);
};
};
int main()
{
twoBitSet<32> bs;
bs[0] = 2;
bs[1] = 3;
bs[2] = 1;
bs[3] = 0;
std::cout << bs[0] << std::endl; // prints 2
std::cout << bs[1] << std::endl; // prints 3
std::cout << bs[2] << std::endl; // prints 1
std::cout << bs[3] << std::endl; // prints 0
}
目前它显然是相当基本的,它只允许使用[]
运算符并且没有任何范围检查。
也许创建 2 个[]
运算符函数(类似于bitset
)会更好——一个只是访问器,一个返回twoBit
对象。
现场演示。
如何创建一个包含 2 位变量和 6 位变量的结构:
struct split
{
uint8_t sixbits : 6;
uint8_t twobits : 2;
}
然后为此创建一个结构数组并仅使用结构的两位部分?
注意:未测试...从这里获取信息。
std::vector<bool>
有你正在寻找的专业。然后,您可以简单地将两个连续的数组元素视为 2 个布尔值中的一个元素,或者如果您不方便在循环中将索引增加 2,请为此编写包装类。使用 2 位变量创建类的问题在于它仍将占用 8 位(1 字节),因为 C++ 中的最小变量大小为 1 字节。
完全自定义的解决方案是创建字符数组(8 位),然后使用移位运算符来使用每个字符的所有位。然而,这将是不必要的复杂,因为您每次访问值时都需要取消移动它们(......这正是std::vector<bool>
专业化的工作方式)。