Size of a bitfield member?

大兔子大兔子 提交于 2019-12-03 02:01:14

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.

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

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.

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.

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!