I'm struggling to understand the following line of code:
if constexpr (std::is_same_v<T, bool>)
{
std::byte change = std::byte(static_cast<uint32_t>(in) << m_addr[1]);
std::byte mask = ~std::byte(1u << m_addr[1]);
dataBlock[m_addr[0]] = (dataBlock[m_addr[0]] & mask) | change;
}
where dataBlock
is a std::vector<std::byte>
, T
is in
's type, and m_addr
is a std::array<std::byte, 2>
. This does bit shifting in order to store the value of a bool inside of a byte. My question is regarding the first line inside the if
statement. For this example, I'll use in = 1
and m_addr[1] = 3
.
From my understanding, static_cast<uint32_t>(in)
creates a uint32_t
given by 00000000,00000000,00000000,00000001
; the left-shift operator turns this into 00000000,00000000,00000000,00001000
, and then this is transformed to an std::byte
.
How does std::byte
choose the byte to store? I assume it stores the LSB, so 00001000
, but I couldn't find any reference confirming this. Is it possible for it to store the MSB (so 00000000
)? If it is, how can I make the below implementation platform-independent?
The definition of std::byte
is: enum class byte : unsigned char {};
(per [cstddef.syn]
)
Thus, when creating a std::byte
from a uint32_t
, the following applies [expr.static.cast]/10
A value of integral or enumeration type can be explicitly converted to a complete enumeration type. If the enumeration type has a fixed underlying type, the value is first converted to that type by integral conversion, if necessary, and then to the enumeration type
From which [conv.integral]/2
applies:
If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo 2n where n is the number of bits used to represent the unsigned type). [ Note: In a two’s complement representation, this conversion is conceptual and there is no change in the bit pattern (if there is no truncation). —end note ]
Thus, in your example, you will get the least significant byte.
Note: references from N4713 (C++17 draft)