10

I need to extact bytes from the bitset which may (not) contain a multiple of CHAR_BIT bits. I now how many of the bits in the bitset I need to put into an array. For example,

the bits set is declared as std::bitset < 40> id;

There is a separate variable nBits how many of the bits in id are usable. Now I want to extract those bits in multiples of CHAR_BIT. I also need to take care of cases where nBits % CHAR_BIT != 0. I am okay to put this into an array of uint8

1
  • 2
    Harsh... if you had less than sizeof(unsigned long) bits, this would be straightforward using bitset::to_ulong. As it is, I don't think there is a simple solution. std::bitset doesn't have something like data() as std::vector does (though the gcc version has an undocumented and experimental _M_getdata function which is just that...)`. Since there is no other thing, you can only access the individual bits separately. Or, serialize to a string or go via a stream, but neither of these is particularly efficient. Commented Nov 28, 2011 at 15:24

3 Answers 3

21

You can use boost::dynamic_bitset, which can be converted to a range of "blocks" using boost::to_block_range.

#include <cstdlib>
#include <cstdint>
#include <iterator>
#include <vector>
#include <boost/dynamic_bitset.hpp>

int main()
{
    typedef uint8_t Block; // Make the block size one byte
    typedef boost::dynamic_bitset<Block> Bitset;

    Bitset bitset(40); // 40 bits

    // Assign random bits
    for (int i=0; i<40; ++i)
    {
        bitset[i] = std::rand() % 2;
    }

    // Copy bytes to buffer
    std::vector<Block> bytes;
    boost::to_block_range(bitset, std::back_inserter(bytes));
}
Sign up to request clarification or add additional context in comments.

3 Comments

One gotcha to watch out for is that the inner type of the vector needs to match the block type that was used to construct the bitset (in this case, unsigned char). If the bitset has 4-byte blocks but the vector has 1-byte blocks, to_block will silently chop off the latter 3 bytes of each block. So, it's somewhat safer to change the vector declaration in Emile's answer to std::vector<Bitset::Block> bytes.
Correction to my comment: the inner type is Bitset::block_type, not Bitset::Block.
@prideout: Added Block typedef to avoid the situation you describe.
3

Unfortunately there's no good way within the language, assuming you need for than the number of bits in an unsigned long (in which case you could use to_ulong). You'll have to iterate over all the bits and generate the array of bytes yourself.

Comments

3

With standard C++11, you can get the bytes out of your 40-bit bitset with shifting and masking. I didn't deal with handling different values rather than 8 and 40 and handling when the second number is not a multiple of the first.

#include <bitset>
#include <iostream>
#include <cstdint>

int main() {
    constexpr int numBits = 40;

    std::bitset<numBits> foo(0x1234567890);
    std::bitset<numBits> mask(0xff);

    for (int i = 0; i < numBits / 8; ++i) {
        auto byte =
            static_cast<uint8_t>(((foo >> (8 * i)) & mask).to_ulong());
        std::cout << std::hex << setfill('0') << setw(2) << static_cast<int>(byte) << std::endl;
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.