简体   繁体   English

位域成员的大小?

[英]Size of a bitfield member?

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 bytes are in mybits.one ?下面的代码自然给了我一个整数的大小,但我如何找出mybits.one有多少位或字节? I've tried sizeof(test.one) but which clearly won't work.我试过sizeof(test.one)但显然行不通。 I realize this is a measure of bits:我意识到这是位的度量:

#include <iostream>

using namespace std;

int main()
{
    struct mybits {
        unsigned int one:15;
    };

    mybits test;
    test.one = 455;
    cout << test.one << endl;
    cout << "The size of test.one is:  " << sizeof(test) << endl;
}

The draft C++ standard says sizeof shall not be applied to a bit-field in section 5.3.3 Sizeof paragraph 1 . C++ 标准草案规定sizeof 不应应用于5.3.3Sizeof1节中的位字段 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:如果您无法控制源代码,则可以使用 bit hacks 来获取位域的大小,而std::bitset则可以更轻松:

#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

Runtime solution, the idea from this discussion: http://social.msdn.microsoft.com/Forums/en-US/7e4f01b6-2e93-4acc-ac6a-b994702e7b66/finding-size-of-bitfield运行时解决方案,这个讨论的想法: 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.打印 15。

Because of padding it is not possible to see number of bits in a bit field using sizeof operator.由于填充,无法使用 sizeof 运算符查看位字段中的位数。

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:根据标准[C++11]expr.sizeof§1 ,在位域上调用sizeof是非法的:

The sizeof operator shall not be applied to ... an lvalue that designates a bit-field. sizeof 运算符不应应用于...指定位字段的左值。

A compile-time solution using constexpr :使用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.在这种情况下,编译器将进入无限循环。

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可以在https://ideone.com/v4BiBH上试用

Note: Works with unsigned bit fields only.注意:仅适用于无符号位字段。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM