c++ - 访问内存中的位

标签 c++

我想一点一点地组装消息,然后将消息作为无符号字符的 vector 处理(例如计算 CRC)

我可以使用 std::vector<bool> 组合消息 OK或 std::bitset

我可以将组装的消息复制到 std::vector 中一点一点地。 (注意:消息被填充,使其长度为整数字节)

// assemble message
std::vector<bool> bitMessage;
...

// copy the bits one by one into bytes and add them to the message
std::vector<unsigned char> myMessage;

// loop over bytes
for (int kbyte = 0;
     kbyte < bitMessage.size() / 8;
     kbyte++)
{
    unsigned char byte = 0;

    // loop over bits
    for (int kbit = 0;
         kbit < 8;
         kbit++)
    {
        // add bit to byte
        byte += bitMessage[8 * kbyte + kbit] << kbit;
    }

    // add byte to message
    myMessage.push_back(byte);
}

这有效。

但是它看起来非常慢!我想使用 std::memcpy .

对于“正常” vector ,我会这样做

memcpy(
  myMessage.data(),
  bitMessage.data(),
  bitMessage.size() / 8 );

memcpy(
  &myMessage[0],
  &bitMessage[0],
  bitMessage.size() / 8 );

但是这两种方法都不适用于 vector<bool>bitset

问题: 有没有办法获取指向存储位的内存的指针?


答案是:不带std::vector<bool>std::bitset

然而,有了一些提示,尤其是来自@Ayxan Haqverdili 的提示,可以编写一个小类来接受单个位并构造一个有礼貌的 std::vector<unsigned char>随着我们的前进。

/** Build a message bit by bit, creating an unsigned character vector of integer length
 * 
 * Hides the messy bit twiddling required,
 * allowing bits to be added to the end of the message
 * 
 * The message is automatically padded at the end with zeroes
 */
class cTwiddle
{
public:
    std::vector<unsigned char> myMessage;

    cTwiddle() : myBitLength(0) {}

    /** add a bit to end of message
     * @param[in] bit 
     */
    void add(bool bit)
    {
        // check if message vector is full
        if (!(myBitLength % 8))
        {
            // add byte to end of message
            myMessage.push_back(0);
        }
        
        // control order bits are added to a byte
        int shift = 7 - (myBitLength % 8);  // add bits from left to right ( MSB first )
        // int shift = (myBitLength % 8);  // add bits from right to left ( LSB first )

        myMessage.back() += (1 & bit) << shift;
        myBitLength++;
    }

private:
    int myBitLength;
};

最佳答案

显然,这些类都没有定义布局。只需编写您自己的类并定义您想要的布局:

template <int size>
class BitSet final {
 private:
  unsigned char buffer[size / 8 + (size % 8 != 0)] = {};

 public:
  constexpr bool get(size_t index) const noexcept {
    return (buffer[index / 8] >> (index % 8)) & 1U;
  }

  constexpr void set(size_t index) noexcept {
    buffer[index / 8] |= (1U << (index % 8));
  }

  constexpr void clear(size_t index) noexcept {
    buffer[index / 8] &= ~(1U << (index % 8));
  }
};

Memcpy-ing 这个类非常好。否则,您还可以提供对字节数组的直接访问。

或者,您可以动态分配缓冲区:

#include <memory>

class DynBitSet final {
 private:
  size_t size = 0;
  std::unique_ptr<unsigned char[]> buffer;

 public:
  explicit DynBitSet(size_t bitsize)
      : size(bitsize / 8 + (bitsize % 8 != 0)),
        buffer(new unsigned char[size]{}) {}

  bool get(size_t index) const noexcept {
    return (buffer[index / 8] >> (index % 8)) & 1U;
  }

  void set(size_t index) noexcept { buffer[index / 8] |= (1U << (index % 8)); }

  void clear(size_t index) noexcept {
    buffer[index / 8] &= ~(1U << (index % 8));
  }

  auto bitSize() const noexcept { return size * 8; }
  auto byteSize() const noexcept { return size; }
  auto const* byteBuffer() const noexcept { return buffer.get(); }
};

关于c++ - 访问内存中的位,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70568513/

相关文章:

c++ - 如何使用 boost::date_time 在本地时间和世界时间之间进行转换?

c++ - 仅当某个模板具有给定类的专门化时,如何 std::enable_if

c++ - 如何在静态 constexpr 类成员中使用 make_tuple() ?

c++ - 可以在参数 C++ 中采用任何类成员的通用函数

c++ - 如何通过字符串名称访问struct属性?

c++ - `std::swap` 在字符串操作中没有按预期工作

c++ - 在函数中传递 char 数组?

c++ - 如何将 std::wstring 包装在 boost::asio::buffer 中?

c++ - Cout 不打印字符串名称(没有显示错误)

c++ - 对于 Msp430 Controller 编码