Size of a bitfield member?

后端 未结 6 1054
傲寒
傲寒 2020-12-29 07:42

Would anyone know how to extract the size of a bit-field member. The below code naturally gives me the size of an integer, but how do I find out how many bits or b

相关标签:
6条回答
  • 2020-12-29 07:49

    A compile-time solution using constexpr:

    struct S
    {
        unsigned int a : 4;
        unsigned int b : 28;
    };
    
    #define GET_BIT_FIELD_WIDTH(T, f) \
        []() constexpr -> unsigned int \
        { \
            T t{}; \
            t.f = ~0; \
            unsigned int bitCount = 0; \
            while (t.f != 0) \
            { \
                t.f >>= 1; \
                ++bitCount; \
            } \
            return bitCount; \
        }()
    
    int main()
    {
        constexpr auto a = GET_BIT_FIELD_WIDTH(S, a);
        constexpr auto b = GET_BIT_FIELD_WIDTH(S, b);
        static_assert(a == 4);
        static_assert(b == 28);
    }
    

    I think it does not invoke any undefined behavior, but it does invoke some implementation-defined behavior:

    1. Wrap-around of bit-fields is implementation-defined.
    2. Above solution will not work for signed fields if right-shift of signed fields uses sign-extension (implemented-defined). The compiler will hit an infinite loop in that case.
    0 讨论(0)
  • 2020-12-29 07:51

    There is no way to get this information (apart from reading the declaration yourself). As per the standard, [C++11]expr.sizeof§1, it's illegal to call sizeof on a bit-field:

    The sizeof operator shall not be applied to ... an lvalue that designates a bit-field.

    0 讨论(0)
  • 2020-12-29 07:52

    Here is a little bit tricky generalized version:

    #include <iostream>
    #include <limits>
    #include <bitset>
    #include <cstring>
    using namespace std;
    
    template <class T>
    T umaxof()
    {
          T t;
          memset(&t, 0xFF, sizeof(T));
          return t;
    }
    
    template <class T>
    size_t bitsof(const T& umax)
    {
        return bitset<sizeof(T)*8>(umax).count();
    }
    
    int main() 
    {
        struct A
        {
            uint32_t bf1:19;
            uint32_t bf2:1;
        };
    
        cout << bitsof(umaxof<A>().bf1) << "\n";
        cout << bitsof(umaxof<A>().bf2) << "\n";
    
        return 0;
    }
    

    It can be tried out at https://ideone.com/v4BiBH

    Note: Works with unsigned bit fields only.

    0 讨论(0)
  • 2020-12-29 07:53

    The draft C++ standard says sizeof shall not be applied to a bit-field in section 5.3.3 Sizeof paragraph 1. If you have control of the source then using an enum sounds much simpler and neater:

    struct mybits
    {
        enum bitFieldSizes
        {
            field1 = 15,
            field2 = 2,
            field3 = 4,
            field4 = 8,
            field5 = 31
        };
    
        unsigned int one : field1 ;  
        unsigned int two : field2 ;  
        unsigned int three : field3 ;
        unsigned int four : field4 ;
        unsigned int five : field5 ;
    };
    

    If you don't have control of the source it is possible to use bit hacks to obtain the size of your bit-field and std::bitset makes it easier:

    #include <iostream>
    #include <bitset>
    
    struct mybits
    {
        unsigned int one : 15 ;  
        unsigned int two : 2 ;  
        unsigned int three : 4 ;
        unsigned int four : 8 ;
        unsigned int five : 31 ;
    };
    
    int main()
    {
        mybits mb1 ;
    
        mb1.one   =  ~0 ;
        mb1.two   =  ~0 ;
        mb1.three =  ~0 ;
        mb1.four  =  ~0 ;
        mb1.five  =  ~0 ;
    
        std::bitset<sizeof(unsigned int)*8> b1(mb1.one);
        std::bitset<sizeof(unsigned int)*8> b2(mb1.two);
        std::bitset<sizeof(unsigned int)*8> b3(mb1.three);
        std::bitset<sizeof(unsigned int)*8> b4(mb1.four);
        std::bitset<sizeof(unsigned int)*8> b5(mb1.five);
    
        std::cout << b1 << ":" << b1.count() << std::endl ;
        std::cout << b2 << ":" << b2.count() << std::endl ;
        std::cout << b3 << ":" << b3.count() << std::endl ;
        std::cout << b4 << ":" << b4.count() << std::endl ;
        std::cout << b5 << ":" << b5.count() << std::endl ;
    }
    

    which produces the following output:

    00000000000000000111111111111111:15
    00000000000000000000000000000011:2
    00000000000000000000000000001111:4
    00000000000000000000000011111111:8
    01111111111111111111111111111111:31
    
    0 讨论(0)
  • 2020-12-29 07:56

    Because of padding it is not possible to see number of bits in a bit field using sizeof operator.

    The only way is to open up the header where the structure is defined, and look it up.

    0 讨论(0)
  • 2020-12-29 08:00

    Runtime solution, the idea from this discussion: http://social.msdn.microsoft.com/Forums/en-US/7e4f01b6-2e93-4acc-ac6a-b994702e7b66/finding-size-of-bitfield

    #include <iostream>
    using namespace std;
    
    int BitCount(unsigned int value)
    {
        int result = 0;
    
        while(value)
        {
            value &= (value - 1);
            ++result;
        }
    
        return result;
    }
    
    int main()
    {
        struct mybits {
            unsigned int one:15;
        };
    
        mybits test;
        test.one = ~0;
    
        cout << BitCount(test.one) << endl;
    
        return 0;
    }
    

    Prints 15.

    0 讨论(0)
提交回复
热议问题