Возможны ли 2-битные массивы битовых полей С++?

У меня есть структура 2-битных битовых полей, например:

struct MyStruct {
    unsigned __int32 info0  : 2;
    unsigned __int32 info1  : 2;
    unsigned __int32 info2  : 2;
   ...
    unsigned __int32 info59 : 2;
};

И еще один, подобный этому, доходит до 120... Есть ли способ записать и адресовать их как массив?


person Robin    schedule 19.08.2014    source источник
comment
Может быть, вы могли бы обернуть что-нибудь вокруг std::bitset<240> ?   -  person Paul R    schedule 19.08.2014
comment
Доступ к обычному массиву осуществляется путем формирования указателя на каждый элемент, и у вас не может быть указателя на битовое поле.   -  person MSalters    schedule 19.08.2014


Ответы (2)


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

static unsigned __int8 infos[30]; // 240 bits allocated

unsigned __int8 getInfo( unsigned short id_num )
{
    return (infos[id_num/4] >> ((2*id_num) % 8) ) & 0x3;
}
// setInfo left as an exercise.

(Возможно, вам придется проверить логику здесь, я ее не проверял.)

person lucasg    schedule 19.08.2014
comment
Вы должны заменить это 4 на sizeof, в противном случае хороший ответ! - person Quentin; 19.08.2014
comment
@Quentin: ну, OP использует __intxx, которые представляют собой типы с определенной длиной в битах, поэтому sizeof здесь не очень полезен. В остальном я согласен. - person lucasg; 19.08.2014
comment
@Квентин sizeof что именно? Насколько я понимаю, 4 здесь bits_in_byte / bitfield_element_width. - person eerorika; 19.08.2014
comment
Хм, действительно. int смутил меня, и я на мгновение подумал, что мы индексируем массив (широких) целых чисел обычного размера 4. Поскольку эти 4 на самом деле являются количеством полей в одном байте, мой комментарий не имеет смысла. Редактировать: но подождите... разве вы не возвращаете ссылку на rvalue прямо здесь? - person Quentin; 19.08.2014
comment
Я ошибаюсь, или этот код возвращает ссылку на временную? - person eerorika; 19.08.2014
comment
Кроме того, я думаю, что сдвиг должен быть умножен на ширину элемента битового поля, равную 2. В противном случае вы никогда не получите доступ к верхней половине элемента массива. - person eerorika; 19.08.2014
comment
@ user2079303: Это было довольно ошибочно. 8*40 тоже не было 240. - person MSalters; 19.08.2014
comment
@MSalters: как я уже сказал, я действительно не проверял ответ. Кроме того, способ укладки 2-битной информации не очень удобен: 3 2 1 0 7 6 5 4 и т. д. - person lucasg; 19.08.2014

Я бы использовал прокси-объект для создания временной ссылки, которую можно было бы использовать для управления 2-битными элементами с использованием синтаксиса массива. Это можно легко изменить для обработки n-битных элементов.

#include <iostream>

class TwoBitArray {
public:
    typedef unsigned char byte;

    TwoBitArray(unsigned size) : bits(new byte[(size + 3) / 4]) {}
    ~TwoBitArray() { delete bits; }

    class tbproxy {
    public:
        tbproxy(byte& b, int pos) : b(b), pos(pos) {}

        // getter
        operator int() const {
            return (b >> (pos * 2)) & 3;
        }

        // setter
        tbproxy operator=(int value) {
            const byte mask = ~(3 << (pos * 2));
            b = (b & mask) | (value << (pos * 2));
            return *this;
        }

    private:
        byte& b;
        int pos;
    };

    // create proxy to manipulate object at index
    tbproxy operator[](int index) const {
        return tbproxy(bits[index/4], index & 3);
    }

private:
    byte* bits;
};

int main() {
    const int size = 20;
    TwoBitArray a(size);
    for (int i = 0; i < size; ++i)
        a[i] = i & 3;
    for (int i = 0; i < size; ++i)
        std::cout << i << ": " << a[i] << std::endl;
}
person Ferruccio    schedule 19.08.2014
comment
Мне нравится ответ, и я, безусловно, ценю время, которое вы потратили на его написание! В моем случае это излишество, поэтому я выберу другой ответ. Однако было бы интересно узнать, почему вы решили использовать прокси-класс вместо простого метода доступа? - person Robin; 25.08.2014
comment
@Robin - Если объект логически образует массив, я бы предпочел получить к нему доступ, используя синтаксис массива. Для меня предоставление пользователю класса чистого, простого и очевидного интерфейса намного перевешивает любые проблемы сложности реализации. Даже если (особенно если :) этим пользователем являюсь я. - person Ferruccio; 25.08.2014