从 std::vector<bool> 获取字节
Posted
技术标签:
【中文标题】从 std::vector<bool> 获取字节【英文标题】:Get bytes from a std::vector<bool> 【发布时间】:2009-02-15 21:02:26 【问题描述】:我有类似以下的内容,在用任意数量的位填充它之后,我需要获取要写入文件的字节。我看不到这样做的方法,而且它似乎很有用,所以我一定遗漏了一些东西。有什么想法吗?
std::vector<bool> a;
a.push_back(true);
a.push_back(false);
a.push_back(false);
a.push_back(true);
a.push_back(false);
a.push_back(true);
a.push_back(true);
a.push_back(false);
【问题讨论】:
确定:你想要包含打包位的字节吗?我的意思是,在您给出的示例中,输出是否只是一个值为 0x96 的字节?还有一件事:期望的字节序是什么? 如果无法读取输出函数,是否还有意义?即使您只回读了一个原始字节==0x00,您仍然不知道向量有多大。 我确实想要打包字节,并且每个位向量的位数都是可变的。 【参考方案1】:std::vector <bool>
实际上不包含布尔值(即字节),它包含位!这主要是一个错误功能,建议您使用std::deque <bool>
,它没有这个“功能”。
如果您希望存储是连续的,请使用std::vector <char>
。
【讨论】:
欢迎模板专业化! hor 位组。他肯定想要 bitset 及其 op>> 和 opboost.org/doc/libs/1_38_0/libs/dynamic_bitset/… 委员会有勇气为 C++0B 放弃export
。可惜他们没有放弃vector<bool>
。
我不会说这是一个错误,这种实现将内存存储成本降低了 8 倍,因为单个字节最多可以存储 8 位。如果您想访问连续缓冲区也没有问题,因为您始终可以按照您的建议使用 vector试试这个
void WriteOut(fstream& stream, const vector<bool>& data)
for (vector<bool>::const_iterator it = data.begin(); it != data.end(); it++)
stream << *it;
【讨论】:
【参考方案3】:bool 通常是一个字节 - 您可以使用 vector::iterator 简单地迭代向量,并以这种方式访问每个值。
std::vector<bool> a;
a.push_back(true);
a.push_back(false);
for(std::vector<bool>::iterator iter = a.begin(); iter != a.end(); ++iter)
std::cout << *iter << std::endl;
将遍历每个布尔值,并将其打印到命令行。打印到文件相对简单。
【讨论】:
布尔值通常不是字节。在许多系统上,它是 CPU 字长,例如32 位,因为这比处理字节要快。 而且vector<bool>
不是 vector<>
或 bool
,这可以说是 C++ 标准最严重的错误特征。【参考方案4】:
做这样的事情
std::vector<bool> a;
a.push_back(true);
a.push_back(false);
//...
for (auto it = a.begin(); it != a.end();) // see 0x for meaning of auto
unsigned b = 0;
for (int i = 0; i < 8*sizeof(b); ++i)
b |= (*it & 1) << (8*sizeof(b) - 1 - i);
++it;
// flush 'b'
因此,您最终要做的是将多块位组合在一起,这里我选择将位组合成本机整数(这对于目标平台来说是最佳的)。我不在这里检查索引,但这是你必须做的事情。我要做的是首先检查我可以提取多少完整的块,然后处理剩余的部分。
另外,请注意,我是从左到右填充位(假设目标架构是 little-endian),这意味着首先填充 msb。
如果您在进行位操作之类的事情,请为您的位制定一个打包方案,并将其作为您的数据结构。 std::bit_vector、std::vector 或 ::dequeue 并不重要。将您的位巧妙地打包到目标平台的本机整数类型中,这将提供最佳性能。
【讨论】:
确实如此。但是,这当然是低效的,所以如果性能很重要,您应该制作自己的容器(提供对原始数据的访问) @John:向响应者***.com/questions/578791/shift-operations 以及你们其他人提问......【参考方案5】:为什么不使用 STL 位集呢?它具有将位集值转换为等效长值或字符串表示形式的特定方法:
http://www.cppreference.com/wiki/stl/bitset/start
【讨论】:
位集是固定大小的 - 也许他想要可变大小? boost.org/doc/libs/1_38_0/libs/dynamic_bitset/…怎么样 我确实想要可变大小,并且列表通常比 long 更长,而 bitset 不会这样做。【参考方案6】:我不记得std::vector<bool>
是否需要打包,很可能不是。如果是,您可以访问其 ::data() 成员以访问原始字节。
【讨论】:
【参考方案7】:首先,您要使用 bit_vector 而不是 vector。
其次,没有办法使用 bit_vector 或 vector 来做你想做的事。它们被设计为集合,并且它们的底层格式对您隐藏(因此它可能决定将每个布尔值存储为单独的字节,而不是打包为每个字节 8 位。
【讨论】:
bit_vector 是非标准的,它只存在于 HP 的 STL 中【参考方案8】:其实你可以这样做:
copy(yourvector.begin(), yourvector.end(), std::ostreambuf_iterator<char>(outputstream));
【讨论】:
【参考方案9】:在查看了上述建议的解决方案后,我最终只是编写了一个完整的功能。
// Count number of bytes needed to contain the bits
// and then copy 8 bit block as bytes.
void writeAsBytes(const vector<bool> & inBits, vector<uint8_t> & outBytes)
int bitOffset = 0;
const int maxBitOffset = (int) inBits.size();
const bool emitMSB = true;
int numBytes = (int)inBits.size() / 8;
if ((inBits.size() % 8) != 0)
numBytes += 1;
for (int bytei = 0; bytei < numBytes; bytei++)
// Consume next 8 bits
uint8_t byteVal = 0;
for (int biti = 0; biti < 8; biti++ )
if (bitOffset >= maxBitOffset)
break;
bool bit = inBits[bitOffset++];
// Flush 8 bits to backing array of bytes.
// Note that bits can be written as either
// LSB first (reversed) or MSB first (not reversed).
if (emitMSB)
byteVal |= (bit << (7 - biti));
else
byteVal |= (bit << biti);
outBytes.push_back(byteVal);
【讨论】:
以上是关于从 std::vector<bool> 获取字节的主要内容,如果未能解决你的问题,请参考以下文章
通过 mpi 发送一个 c++ std::vector<bool>
C++ - 将 char 引用转换为 bool 引用(std::vector<bool>)