Search code examples
c++c++17std-byte

Does std::byte constructor extract LSB or MSB from integer?


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?


Solution

  • 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)