Как хранить битовый массив в C ++? - PullRequest
11 голосов
/ 20 октября 2011

Каков наилучший способ хранения битового массива в C ++ (без Boost, только стандартные контейнеры), представляющего, например, битовый массив выделения тома?

Я думал, что std::vector<bool> - отличная идея, но очевидно, что это зло и устарело , так есть ли лучший выбор?

Также:

Если у меня в памяти есть байтовый массив, как бы я скопировал их врекомендуемый контейнер?
(у меня проблемы с вычислением этого для vector<bool>.)

Ответы [ 6 ]

2 голосов
/ 16 мая 2017

Просто опубликовав это 6 лет спустя для потомков: как сказал один из комментаторов, я пришел к выводу, что прекрасно , чтобы использовать std::vector<bool> в качестве своего специализированного типа.Единственное, с чем вам нужно быть осторожным, это не относиться к нему как к стандартному bool контейнеру, поскольку это не так.

2 голосов
/ 20 октября 2011

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

Пример:

char bitarray[4]; // since 4*8 this array actually contains 32 bits

char getBit(int index) {
    return (bitarray[index/8] >> 7-(index & 0x7)) & 0x1;
}

void setBit(int index, int value) {
    bitarray[index/8] = bitarray[index/8] | (value & 0x1) << 7-(index & 0x7);
}

Конечно, эти операции обычно сравнительно медленны, но если проблема с памятьюэто достойный путь.Для этого я выбрал символы, чтобы уменьшить количество необходимых смен.Однако это может быть быстрее с целыми числами.

1 голос
/ 20 октября 2011

Для ванильного C ++ есть std :: bitset.

Bitset очень похож на vector (также известный как bit_vector): он содержит набор битов и обеспечивает постоянный доступ к каждый бит. Есть два основных различия между битами и вектор. Во-первых, размер набора битов не может быть изменен: набор битов параметр шаблона N, который указывает количество бит в бит, должен быть целочисленной константой. Во-вторых, набор битов не является последовательностью; на самом деле это вовсе не контейнер STL.

У Мэтта Остерна есть хорошая статья о его использовании.

Также : Если ваш байтовый массив (битовый массив?) Помещается в беззнаковый long, то вы можете назначить его напрямую в std :: bitset:

unsigned long myByteArray = 0xABCD;
std::bitset<32> bitten( myByteArray );
0 голосов
/ 05 марта 2019

Библиотека мощных битовых массивов C / С ++: https://github.com/noporpoise/BitArray

0 голосов
/ 20 октября 2011

Подойдет std :: bitset , если ваш битовый массив имеет фиксированный размер.
В качестве примечания также есть std :: dynamic_bitset, но я не уверен на 100%, что он вошел в стандарт.

0 голосов
/ 20 октября 2011

Я думаю, что некоторые замечания, сделанные на сайте, на который вы ссылаетесь, кстати, не верны. Почти на каждом компьютере размер бита на самом деле составляет один байт (такой же, как у символа), поскольку компьютеры могут адресовать только байт, а не бит в пределах байта (если бы вы могли, то у вас была бы только одна восьмая часть адресного пространства, которое у вас есть в настоящее время. с байтами)

Я бы просто использовал байт для вашего вектора, потому что он дает другим людям, которые читают ваш код, лучшее представление об объеме памяти вашего приложения.

Оперативная память очень распространена в современных компьютерах, поэтому вы можете использовать более крупные целочисленные типы, но реально вы не можете получить меньший размер, чем байт.

Чтобы скопировать данные из одного контейнера в другой, сначала создайте итератор для контейнера

vector :: iterator myItr = myVector.begin ()

и итерация по вектору с циклом while или циклом for, пока myItr не достигнет myVector.end ().

Например

for(vector<bool>::iterator myItr = myVector.begin(); myItr<myVector.end(); ++myItr)
{
   otherContainer.append(*myItr);
}
...