Search code examples
c++arrayshexbytebit

Convert array of bits to an array of bytes


I want to convert an array of bits (bool* bitArray) where the values are 1s and 0s into an array of bytes (unsigned char* byteArray) where the values at each index would be one byte. For ex, index 0~7 in bitArray would go into byteArray[1].

How would I go about doing this? Assuming that I already have an array of bits (but the amount would be subject to change based on the incoming data). I am not worried about having it divisible by 8 because I will just add padding at the end of the bitArray to make it divisible by 8.


Solution

  • Just just use bit shifts or a lookup array and and combine numbers with 1 bit set each with bitwise or for 8 bits at a time:

    int main() {
        bool input[] = {
            false, false, false, true, true, true, false, false, false,
            false, false, false, true, true, true, false, false, false,
            false, false, false, true, true, true, false, false, false,
            false, false, false, true, true, true, false, false, false,
        };
    
        constexpr auto len = sizeof(input) / sizeof(*input);
        constexpr size_t outLen = ((len % 8 == 0) ? 0 : 1) + len / 8;
    
        uint8_t out[outLen];
    
        bool* inPos = input;
        uint8_t* outPos = out;
    
        size_t remaining = len;
    
        // output bytes where there are all 8 bits available
        for (; remaining >= 8; remaining -= 8, ++outPos)
        {
            uint8_t value = 0;
            for (size_t i = 0; i != 8; ++i, ++inPos)
            {
                if (*inPos)
                {
                    value |= (1 << (7 - i));
                }
            }
            *outPos = value;
        }
    
        if (remaining != 0)
        {
            // output byte that requires padding
            uint8_t value = 0;
            for (size_t i = 0; i != remaining; ++i, ++inPos)
            {
                if (*inPos)
                {
                    value |= (1 << (7 - i));
                }
            }
            *outPos = value;
        }
    
        for (auto v : out)
        {
            std::cout << static_cast<int>(v) << '\n';
        }
    
        return 0;
    }
    

    The rhs of the |= operator could also be replaced with a lookup in the following array, if you consider this simpler to understand:

    constexpr uint8_t Bits[8]
    {
        0b1000'0000,
        0b0100'0000,
        0b0010'0000,
        0b0001'0000,
        0b0000'1000,
        0b0000'0100,
        0b0000'0010,
        0b0000'0001,
    };
    
    ...
    value |= Bits[i];
    ...