Search code examples
c++bit-fieldsbitmask

Can you extract bitmask directly from bitfield in C++?


Considering following example:

#include <iostream>

using namespace std;

struct Test
{
    uint8_t A:1;
    uint8_t B:1;
    uint8_t C:1;
    uint8_t D:1;
};

int main()
{
    Test test;
    test.A = 1;
    test.B = 0;
    test.C = 1;
    test.D = 0;
    
    int bitmask = test.A | (test.B << 1) | (test.C << 2) | (test.D << 3);
    
    cout << "Size: " << sizeof(test) << ", bitmask: " << bitmask;

    return 0;
}

I'm assuming that the data in the bitfield is represented as bitmask somehow? I was wondering if there is a way to get a bitmask directly, without having to go through and shift all members. In this case it's not a big deal, but if you have large bitfield it can get pretty tedious.

For example it would be great if I could do something like this:

int bitmask = (int)test;

Of course that doesn't work. Any way to achieve similar robustness?


Solution

  • Assuming you want to convert the entire struct, and there exists an integral type with the same size as the struct:

    Test test;
    test.A = 1;
    test.B = 0;
    test.C = 1;
    test.D = 0;
    
    cout << (int)std::bit_cast<char>(test) << '\n';
    

    std::bit_cast is a C++20 feature.

    char is used here because it has the same size as Test. I'm casting the result to int, because otherwise cout interpretes the resulting number as a character code.


    The alternative solution is to memcpy the struct (or a part of it) to an integer:

    char ch;
    std::memcpy(&ch, &test, 1);
    cout << (int)ch << '\n';
    

    Unlike bit_cast, this doesn't require a modern compiler, and allows you to inspect a specific part of the struct (assuming the part is byte-aligned).