Подтвердить что ты не робот

Размер члена битового поля?

Кто-нибудь знает, как извлечь размер члена битового поля. В приведенном ниже коде естественно указывается размер целого числа, но как узнать, сколько бит или байтов находится в mybits.one? Я пробовал sizeof(test.one), но это явно не сработает. Я понимаю, что это мера бит:

#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;
}
4b9b3361

Ответ 1

Решение времени выполнения, идея из этого обсуждения: 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;
}

Отпечатки 15.

Ответ 2

Из-за заполнения невозможно увидеть число бит в битовом поле с помощью оператора sizeof.

Единственный способ открыть заголовок, где определена структура, и посмотреть его.

Ответ 3

Невозможно получить эту информацию (кроме прочтения декларации самостоятельно). Согласно стандарту, [C++11]expr.sizeof§1, незаконно вызывать sizeof в битовом поле:

Оператор sizeof не должен применяться к... значению l, которое обозначает бит-поле.

Ответ 4

черновик стандарта С++ говорит, что sizeof не применяется к битовому полю в разделе 5.3.3 Размер пункта 1. Если у вас есть контроль источника, тогда использование перечисления звучит намного проще и опереже:

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

Если у вас нет контроля над источником, вы можете использовать бит-хаки для получения размера вашего битового поля и 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 ;
}

который производит следующий вывод:

00000000000000000111111111111111:15
00000000000000000000000000000011:2
00000000000000000000000000001111:4
00000000000000000000000011111111:8
01111111111111111111111111111111:31

Ответ 5

Вот немного сложная обобщенная версия:

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

Его можно опробовать в https://ideone.com/v4BiBH

Примечание. Работает только с полями без знака.