DEV Community

Cover image for Bit manipulations got easier in c++20 with <bit> header.
Vaishakh Menon
Vaishakh Menon

Posted on • Updated on

Bit manipulations got easier in c++20 with <bit> header.

Starting from cpp20 checking for the machine's endianness (wiki) got easier, the new bit header will be having new enum std::endian, and lot of other bit manipulation stuffs.

For those of you guys who is not aware of machine endianness, it is basically the sequential order in which bytes are organized in a word.
For example in a Little Endian(LE) system (which are almost 90% of the systems), a 0x1234 will be represented as below.

MSB             LSB
0001 0010 0011 0100
  1    2    3    4
Enter fullscreen mode Exit fullscreen mode

While on a Big Endian(BE) system it will be in reverse order.

MSB             LSB
0011 0100 0001 0010
  3    4    1    2
Enter fullscreen mode Exit fullscreen mode

which in hex will be 0x3412, as I said above it will be organized in a word.
If you need more info do read the wiki link above.

Now this is very helpful and a big deal for those who are working in low level stuffs, like who writes network socket programming, portable embedded code etc.

Earlier one of the way to calculate the byte order of the system you have to write your own code.

enum ENDIAN
{
    LITTLE,
    BIG
};

const ENDIAN getEndian()
{
    uint32_t word = 1;
    uint8_t *first_byte = reinterpret_cast<uint8_t*>(&word);
    if (first_byte)
        return ENDIAN::LITTLE;
    else
        return ENDIAN::BIG;
}
Enter fullscreen mode Exit fullscreen mode

something like above, and every one have their own way of finding it out as it was not standardized.

Now you can do something like this and it's done.

#include <iostream>
#include <bit>

int main()
{
    (std::endian::native == std::endian::big) 
                ? std::cout << "big-endian\n" 
                : std::cout << "little-endian\n";

    return 0;
}
Enter fullscreen mode Exit fullscreen mode

Other than BE and LE there is also an other mythical being called as mixed-endian or middle-endian and the only known practical use of it was in PDP-11 system. If the above 2 is not the one then you can add an else if statement and it will give you the middle-endian, but this is in extremely rare case.

The header has other useful features also like bit rotation, byte cast etc..

  • Bit Rotation
#include <iostream>
#include <bit>
#include <bitset>
#include <cstdint>

int main()
{
    const std::uint8_t b = 0b00001111;
    std::cout << "b          = " << std::bitset<8>(b) << '\n';
    std::cout << "rotl(b,4)  = " << std::bitset<8>(std::rotl(b, 4)) << '\n';
    std::cout << "rotr(b,2)  = " << std::bitset<8>(std::rotr(b, 1)) << '\n';

    return 0;
}

Output:-

b          = 00001111
rotl(b,4)  = 11110000
rotr(b,2)  = 10000111

Enter fullscreen mode Exit fullscreen mode
  • Byte Cast
#include <iostream>
#include <bit>
#include <bitset>
#include <cstdint>
#include <climits>

int main()
{
    constexpr uint64_t i = ULLONG_MAX;
    constexpr auto bit = std::bit_cast<std::uint64_t>(i);
    std::cout << i << "\n";
    std::cout << std::bitset<64>(bit) << "\n";

    return 0;
}

Output:-
18446744073709551615
1111111111111111111111111111111111111111111111111111111111111111

Enter fullscreen mode Exit fullscreen mode

Hope this will make lives easier going forward, as we will be able to use things out of the box instead of using external libs like Boost.

Top comments (0)