Bit manipulations got easier in c++20 with <bit> header.
Tags: cpp, cpp20
Published: 2023-10-24 05:39:39

Starting from cpp20 checking for the machine's endianness ([wiki](https://en.wikipedia.org/wiki/Endianness)) got easier, the new [bit](https://en.cppreference.com/w/cpp/header/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
```

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

```
MSB             LSB
0011 0100 0001 0010
  3    4    1    2
```

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;
}
```

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;
}
```

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](https://en.wikipedia.org/wiki/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 <bit> 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

```

- 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

```


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.