从 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 &lt;bool&gt; 实际上不包含布尔值(即字节),它包含位!这主要是一个错误功能,建议您使用std::deque &lt;bool&gt;,它没有这个“功能”。

如果您希望存储是连续的,请使用std::vector &lt;char&gt;

【讨论】:

欢迎模板专业化! hor 位组。他肯定想要 bitset 及其 op>> 和 opboost.org/doc/libs/1_38_0/libs/dynamic_bitset/… 委员会有勇气为 C++0B 放弃 export。可惜他们没有放弃vector&lt;bool&gt; 我不会说这是一个错误,这种实现将内存存储成本降低了 8 倍,因为单个字节最多可以存储 8 位。如果您想访问连续缓冲区也没有问题,因为您始终可以按照您的建议使用 vector【参考方案2】:

试试这个

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&lt;bool&gt; 不是 vector&lt;&gt;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&lt;bool&gt; 是否需要打包,很可能不是。如果是,您可以访问其 ::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> 获取字节的主要内容,如果未能解决你的问题,请参考以下文章

运算符 |= 在 std::vector<bool> 上

通过 mpi 发送一个 c++ std::vector<bool>

C++ - 将 char 引用转换为 bool 引用(std::vector<bool>)

std::vector<bool>中的坑

bcc32:专注于`std::vector<bool>`时出现奇怪的错误

在 C++ 中使用 std::vector<bool> 对象是不是可以接受,还是应该使用替代方法?