-1

I want to cast an array of bits into a byte, it works by using a loop and bitshift, but I think it would be cost inefective if run repeatedly (I might be wrong). So I wanted to use a pointer with reinterpret_cast.

It works when I use it between uint8_t and uint16_t

uint16_t a = 32769; uint8_t *aPtr = reinterpret_cast<uint8_t*>(&a); std::cout << (int) a << " => {" << (int)*(aPtr) << ", " << (int)*(aPtr + 1) << "}" << std::endl; uint8_t b[2] = {1, 128}; uint16_t *bPtr = reinterpret_cast<uint16_t*>(&b); std::cout << "{" << (int)b[0] << ", " << (int)b[1] << "} => " << (int)*bPtr << std::endl; 

It gives

32769 => {1, 128} {1, 128} => 32769 

But when I try it with bool and uint8_t it won't work

bool c[8] = {1, 1, 1, 1, 1, 1, 1, 1}; uint8_t *cPtr = reinterpret_cast<uint8_t*>(&c); std::cout << "{"; for(int i=0; i<8; i++) std::cout << c[i] << (i < 7 ? ", " : ""); std::cout << "} => " << (int)*cPtr << std::endl; uint8_t d = 255; bool *dPtr = reinterpret_cast<bool*>(&d); std::cout << (int)d << " => {"; for(int i=0; i<8; i++) std::cout << *(dPtr + i) << (i < 7 ? ", " : ""); std::cout << "}" << std::endl; 

With result

{1, 1, 1, 1, 1, 1, 1, 1} => 1 255 => {255, 1, 1, 1, 1, 1, 1, 1} 

Is it impossible to do it with reinterpret_cast? or I just do it wrong? or even my guess about loop and bitshift is wrong in the first place?

8
  • 3
    Do you understand that a bool occupies one byte? There are 7 unused zero bits in it. Commented Aug 4 at 4:23
  • 5
    An array of bool is not an array of bits. The closest you will come to an array of bits in C++ are std::bitset and std::vector<bool>. std::bitset has methods which convert to an unsigned integer. Commented Aug 4 at 4:55
  • 1
    To answer the question asked, you cannot use reinterpret_cast to convert an array of bool into an integer. Commented Aug 4 at 4:58
  • 2
    std::bitset has methods which convert to an unsigned integer, however it has a fixed size (fixed but still chosen by you). IF that is not a problem then you should take a look. Judging by your code above std::bitset<16> c = ...; uint16_t d = c.to_ulong(); seems to be what you want. Commented Aug 4 at 5:01
  • 1
    C++ has no "array of bits". Is this what you are calling uint8_t b[2]? Is this what you are calling bool c[8]? Commented Aug 4 at 5:05

2 Answers 2

1

You cannot use reinterpret_cast to convert from an array of bool to an integer. Apart from anything else the memory layout of an integer and a bool array are different.

However C++ has a std::bitset class which seems to do what you want, e.g.

#include <bitset> std::bitset<8> c = "11111111"; uint8_t d = c.to_ulong(); 

A std::bitset has a fixed size (eight in the above example) but judging by the code you posted that is not a problem. Conversion routines to and from integers and strings exist, as well as methods to manipulate individual bits, bitwise logical operations and shift operations.

Bitset reference

Sign up to request clarification or add additional context in comments.

Comments

0

Note your input value already IS an array of bits!
Anyway here is an example of what I mean (based on a class I had lying around). Kind of does what bitset does, but you can see a bit of what is under the hood (pun intended)
Demo : https://godbolt.org/z/YY7EKq5cd

#include <cassert> #include <cstdint> #include <concepts> #include <limits> #include <type_traits> #include <iostream> template <std::unsigned_integral type_t> class Bits final { public: using value_type = type_t; constexpr Bits() noexcept : m_value{0} {} explicit constexpr Bits(type_t value) noexcept : m_value{value} {} constexpr Bits operator|(Bits rhs) const noexcept { return Bits{m_value | rhs.m_value}; } constexpr Bits operator&(Bits rhs) const noexcept { return Bits{m_value & rhs.m_value}; } constexpr Bits operator^(Bits rhs) const noexcept { return Bits{m_value ^ rhs.m_value}; } constexpr Bits operator~() const noexcept { return Bits{~m_value}; } constexpr Bits& operator|=(Bits rhs) noexcept { m_value |= rhs.m_value; return *this; } constexpr Bits& operator&=(Bits rhs) noexcept { m_value &= rhs.m_value; return *this; } constexpr Bits& operator^=(Bits rhs) noexcept { m_value ^= rhs.m_value; return *this; } constexpr bool test(std::size_t bit) const noexcept { return (m_value & (type_t{1} << bit)) != 0; } constexpr void set(std::size_t bit) noexcept { m_value |= (type_t{1} << bit); } constexpr void clear(std::size_t bit) noexcept { m_value &= ~(type_t{1} << bit); } constexpr void toggle(std::size_t bit) noexcept { m_value ^= (type_t{1} << bit); } constexpr std::size_t popcount() const noexcept { return std::popcount(m_value); } constexpr std::size_t count_trailing_zeros() const noexcept { return std::countr_zero(m_value); } constexpr std::size_t count_leading_zeros() const noexcept { return std::countl_zero(m_value); } constexpr type_t value() const noexcept { return m_value; } constexpr void set_value(type_t v) noexcept { m_value = v; } // Proxy for bit reference using set/clear class bitref { Bits& bits_; std::size_t idx_; public: bitref(Bits& bits, std::size_t idx) : bits_(bits), idx_(idx) {} operator bool() const { return bits_.test(idx_); } bitref& operator=(bool v) { if (v) bits_.set(idx_); else bits_.clear(idx_); return *this; } }; constexpr bitref operator[](int idx) { if (idx != 0 && idx != 1) throw std::out_of_range("Bits[]: only 0 or 1 allowed"); return bitref(*this, idx); } constexpr bool operator[](int idx) const { if (idx != 0 && idx != 1) throw std::out_of_range("Bits[]: only 0 or 1 allowed"); return test(idx); } private: type_t m_value; }; int main() { Bits<std::uint16_t> b; assert(b.value() == 0); b[0] = true; b[1] = false; assert(b[0] == true); assert(b[1] == false); b[1] = true; assert(b[1] == true); try { b[2] = true; assert(false); } catch (const std::out_of_range&) {} std::cout << "Bits[] operator test passed!\n"; return 0; } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.