位摆弄很少是容易的。这里有一个完整的实例,说明如何做你想做的事。
的一个大问题是在这里阅读和跨字节界限写数块。如果你将它们分解成一口大小的块,问题总是更容易,如果你会赦免双关语。
首先我创建比如std :: bitset的一个类,它可以包住用户定义的缓冲区。它让我们在二进制数据的大缓冲区中摆弄单个位。
#include <cassert> // for assert
#include <cstring> // for memset
// A wrapper for a data buffer providing bit-level access.
class BitBuffer {
public:
BitBuffer (unsigned char *src_buffer, size_t byte_size)
: m_data(src_buffer), m_size(byte_size)
{
if (m_size) assert(m_data);
}
// Clear the buffer (set all bits to 0).
void clear() {
memset(m_data, 0, m_size);
}
// Get an individual bit's value.
bool get (size_t bitpos) const {
assert(bitpos/8 < m_size);
return m_data[ bitpos/8 ] & (1 << (bitpos % 8));
}
// Set an individual bit's value.
void set (size_t bitpos, bool val=true) {
assert(bitpos/8 < m_size);
if(val) {
m_data[ bitpos/8 ] |= (1 << (bitpos % 8));
} else {
m_data[ bitpos/8 ] &= ~(1 << (bitpos % 8));
}
}
// Switch off a bit.
void reset (size_t bitpos) {
set(bitpos, false);
}
// Flip a bit.
void flip (size_t bitpos) {
set(bitpos, ! get(bitpos));
}
// Return the size of the buffer in bytes.
size_t byte_size() const { return m_size; }
// Return the size of the buffer in bits.
size_t bit_size() const { return m_size * 8; }
// Return a const pointer to the buffer.
unsigned char const * buffer() const { return m_data; }
private:
unsigned char * m_data;
size_t m_size;
};
然后我写了一些函数来获取并首先从缓冲区,MSB位设置的块。
unsigned get_bits (BitBuffer& buffer, size_t offset, size_t bit_size)
{
unsigned bits = 0;
for (size_t i = 0; i < bit_size; i++) {
// We reverse the order of the bits, so the first bit read
// from the buffer maps to the high bit in 'bits'.
bits |= (buffer.get(offset + i) << (bit_size - 1 - i));
}
return bits;
}
void set_bits (BitBuffer& buffer, size_t offset, size_t bit_size, unsigned bits)
{
for (size_t i = 0; i < bit_size; i++) {
// We reverse the order of the bits, so the high bit of 'bits'
// gets written to the buffer first.
bool bit_value = bits & (1 << (bit_size - 1 - i));
buffer.set(offset + i, bit_value);
}
}
和测试工具:
#include <cstdio>
// Print the bits of the buffer to stdout.
void dump_buffer (BitBuffer& buffer)
{
for (size_t i = 0; i < buffer.bit_size(); i++) {
printf("%i", buffer.get(i));
}
printf("\n");
}
int main()
{
const size_t byte_size = 4; // size of buffer in bytes
unsigned char * raw_buffer = new unsigned char[ byte_size ];
BitBuffer buffer(raw_buffer, byte_size);
buffer.clear();
printf("Test #0: contents of 4-byte buffer:\n");
// Show the buffer.
dump_buffer(buffer);
printf("\nTest #1: setting and flipping bits:\n");
// Set some bits
buffer.set(5);
buffer.set(10);
buffer.set(12);
buffer.set(31);
// Show the buffer.
dump_buffer(buffer);
// Read some bits.
printf("Value at 12 before flip: %i\n", buffer.get(12));
buffer.flip(12);
printf("Value at 12 after flip: %i\n", buffer.get(12));
printf("\nTest #2: setting all 1's, and writing 5, length 4 to offset 6:\n");
// Fill with 1's.
set_bits(buffer, 0, 32, 0xFFFFFFFF);
// Set 5 at offset 6, bit size 4.
set_bits(buffer, 6, 4, 5);
assert(get_bits(buffer, 6, 4) == 5);
// Show the buffer.
dump_buffer(buffer);
// All done.
delete raw_buffer;
return 0;
}
进行编译,只转储这一切都在一个文件和编译。测试运行的输出:
Test #0: contents of 4-byte buffer:
00000000000000000000000000000000
Test #1: setting and flipping bits:
00000100001010000000000000000001
Value at 12 before flip: 1
Value at 12 after flip: 0
Test #2: setting all 1's, and writing 5, length 4 to offset 6:
11111101011111111111111111111111
让我知道你是否觉得它有用,或者如果你有任何问题。
对这个需求使用模板似乎对我无用 –
@stefanbachert模板在代码将被使用的地方是合理的,但是你是对的,它们在这里没用,所以我删除了它们。 – wroniasty