C++ 从`std::vector<;中的位获取整数;char>`

C++ 从`std::vector<;中的位获取整数;char>`,c++,bytearray,bit-manipulation,bit,bit-shift,C++,Bytearray,Bit Manipulation,Bit,Bit Shift,我有一个向量,我希望能够从向量中的一系列位中得到一个无符号整数。例如 我似乎无法编写正确的操作来获得所需的输出。我预期的算法如下所示: 和第一个字节带有(0xff>>左侧字节中未使用的位) 开始%8); 返回\u type first\u wide=first; 首先是一个有趣的问题。对于一些系统工作,我也做过类似的工作 你的字符是8位宽?还是16位?你的整数有多大?32还是64 暂时忽略向量的复杂性 把它想象成一个比特数组 你有多少位?你有8个字符 需要计算起始字符、提取位数、结束字符、

我有一个
向量
,我希望能够从向量中的一系列位中得到一个无符号整数。例如

我似乎无法编写正确的操作来获得所需的输出。我预期的算法如下所示:

  • 第一个字节带有
    (0xff>>左侧字节中未使用的位)
  • 开始%8);
    返回\u type first\u wide=first;
    
    首先是一个有趣的问题。对于一些系统工作,我也做过类似的工作

    • 你的字符是8位宽?还是16位?你的整数有多大?32还是64
    • 暂时忽略向量的复杂性
    • 把它想象成一个比特数组
    • 你有多少位?你有8个字符
    • 需要计算起始字符、提取位数、结束字符、位位数和中间字符数。
    • 对于第一个部分字符,您将需要按位and&键
    • 对于最后一个部分字符,您需要按位and&键
    • 您将需要左移>),具体取决于从哪个顺序开始
    • 整数的endian值是多少
    在某个时刻,您将计算数组中的一个索引,它是bitindex/char\u bit\u width,您将值171作为bitindex,将值8作为char\u bit\u width,因此您将最终计算出这些有用的值:

    • 171/8=23//第一个字节的位置
    • 171%8=第一个字符/字节中的3//位
    • 8-171%8=最后一个字符/字节中的5//位
    • sizeof(整数)=4
    • sizeof(integer)+(171%8)>0?1:0)//要检查多少个数组位置

    需要一些汇编…

    有一件事你肯定错过了,我认为:你在向量中索引位的方式不同于你在问题中给出的方式。也就是说,根据你概述的算法,位的顺序将类似于
    765443210 | 1514131211098 | 232221…
    呃,你的整个算法,但这一个在第一步就被遗漏了。

    你犯了两个主要错误。第一个是:

    first_wide <<= byte_width;
    
    应该是

    auto byte_offset = (byte_end - byte_i) * bits_per_byte;
    
    括号中的值必须是要右移的字节数,这也是字节_i远离末尾的字节数。值
    byte_width-byte_i
    没有语义意义(一个是增量,另一个是索引)

    代码的其余部分很好。不过,这个算法有两个问题

    首先,当使用结果类型累积位时,假设左侧有多余的空间。如果右侧边界附近有设置位,并且选择范围会导致位移位,则情况并非如此。例如,尝试运行

    bits.get_bits<uint16_t>(11, 27);
    
    对于位字符串
    0001011 01000000
    ,预期结果应该是6976,但是当前实现对于位字符串
    11111 011 01000000
    返回-1216

    我在下面介绍了我的实现,它从右到左构建位字符串,将位放置在正确的位置,以避免上述两个问题:

    template<class ReturnType>
    ReturnType get_bits(int start, int end) {
      int max_bits = kBitsPerByte * sizeof(ReturnType);
      if (end - start > max_bits) {
        start = end - max_bits;
      }
    
      int inclusive_end = end - 1;
      int byte_start = start / kBitsPerByte;
      int byte_end = inclusive_end / kBitsPerByte;
    
      // Put in the partial-byte on the right
      uint8_t first = bytes_[byte_end];
      int bit_offset = (inclusive_end % kBitsPerByte);
      first >>= 7 - bit_offset;
      bit_offset += 1;
      ReturnType ret = 0 | first;
    
      // Add the rest of the bytes
      for (int i = byte_end - 1; i >= byte_start; i--) {
        ReturnType tmp = (uint8_t) bytes_[i];
        tmp <<= bit_offset;
        ret |= tmp;
        bit_offset += kBitsPerByte;
      }
    
      // Mask out the partial byte on the left
      int shift_amt = (end - start);
      if (shift_amt < max_bits) {
        ReturnType mask = (1 << shift_amt) - 1;
        ret &= mask;
      }
    }
    
    模板
    ReturnType获取_位(int开始,int结束){
    int max_bits=kBitsPerByte*sizeof(返回类型);
    if(结束-开始>最大字节){
    开始=结束-最大\u位;
    }
    int inclusive_end=end-1;
    int byte_start=start/kBitsPerByte;
    int byte_end=包含字节/kBitsPerByte;
    //输入右边的部分字节
    uint8_t first=bytes_[byte_end];
    整数位的偏移量=(包括结尾%kBitsPerByte);
    第一个>>=7位\u偏移量;
    位u偏移量+=1;
    ReturnType ret=0 | first;
    //添加剩余的字节
    对于(int i=byte\u end-1;i>=byte\u start;i--){
    ReturnType tmp=(uint8_t)字节[i];
    
    tmp这对无符号整数非常有效谢谢!我正在研究有符号整数-我不完全确定
    get_位(14,22)的期望输出
    马上就到了!我希望很快就会回来更新,或者如果我发现这是我想要的行为,给你一个记号:)这段代码似乎对
    位不起作用。获取位(0,32)
    -它返回零,而不是预期的
    519053860746
    您是对的。错误是由于结果在结尾被屏蔽的方式造成的。左移将位移到不重要的位置,导致位掩码为0。我添加了一个修复。
    auto byte_offset = (byte_end - byte_i) * bits_per_byte;
    
    bits.get_bits<uint16_t>(11, 27);
    
    bits.get_bits<int16_t>(5, 21);
    
    template<class ReturnType>
    ReturnType get_bits(int start, int end) {
      int max_bits = kBitsPerByte * sizeof(ReturnType);
      if (end - start > max_bits) {
        start = end - max_bits;
      }
    
      int inclusive_end = end - 1;
      int byte_start = start / kBitsPerByte;
      int byte_end = inclusive_end / kBitsPerByte;
    
      // Put in the partial-byte on the right
      uint8_t first = bytes_[byte_end];
      int bit_offset = (inclusive_end % kBitsPerByte);
      first >>= 7 - bit_offset;
      bit_offset += 1;
      ReturnType ret = 0 | first;
    
      // Add the rest of the bytes
      for (int i = byte_end - 1; i >= byte_start; i--) {
        ReturnType tmp = (uint8_t) bytes_[i];
        tmp <<= bit_offset;
        ret |= tmp;
        bit_offset += kBitsPerByte;
      }
    
      // Mask out the partial byte on the left
      int shift_amt = (end - start);
      if (shift_amt < max_bits) {
        ReturnType mask = (1 << shift_amt) - 1;
        ret &= mask;
      }
    }