2010-10-22 3 views
13

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

номер Подход 1 (AN 1)

struct BIT 
{ 
    int data : 1 
}; 

int main() 
{ 
    BIT a[100]; 
    return 0; 
} 

номер Подход 2 (AN 2)

int main() 
{ 
    std::bitset<100> BITS; 
    return 0; 
} 

Почему бы кто-то предпочитает 2 над 1?

+3

Процитирую страницу cplusplus.com на BitSet, «Класс очень похож на обычный массив, но для оптимизации распределения пространства». Если ваш ints равен 4 байтам, биты используют в 32 раза меньше места. – AlcubierreDrive

+2

Ваша структура 'BIT' будет выровнена так или иначе (по крайней мере) на один байт. – Archie

+0

@Jon, сообщение это как ответ. (Это хороший момент.) –

ответ

15

Потому что подход эл. 2 фактически использует 100 бит памяти, плюс некоторые очень незначительные (постоянные) накладные расходы, а nr. 1 обычно использует четыре байта хранения на структуру Bit. В общем случае размер struct составляет по меньшей мере один байт в соответствии с стандартом C++.

#include <bitset> 
#include <iostream> 

struct Bit { int data : 1; }; 

int main() 
{ 
    Bit a[100]; 
    std::bitset<100> b; 
    std::cout << sizeof(a) << "\n"; 
    std::cout << sizeof(b) << "\n"; 
} 

печатает

400 
16 

Помимо этого, bitset окружит массив битов в хорошем представлении объекта с большим количеством полезных операций.

+0

Каким образом вывод 'sizeof (b)' равен 16? 100 бит означает 100/8 байт. Что мне не хватает? – CLOWN

+1

Он должен быть «закруглен» до кратного восьми, поскольку байт представляет собой наименьшую единицу хранения, которая непосредственно адресуется. Попробуйте выполнить компиляцию с 128 бит в наборе, тогда это все равно 16. 'bitset' использует некоторые трюки, чтобы притворяться, что это фактически биты адресации. –

+0

Мой предыдущий комментарий был наполовину прав. Он округлен до нескольких байтов, поскольку четырехбайтовый блок является самым быстрым для 32-разрядного компьютера. Но в любом случае байт является наименьшим адресуемым модулем, поэтому он составляет не менее 13 (100/8 = 12,5, а половина байта не адресуется). Прости, пятница. –

0

Подход № 1, скорее всего, будет скомпилирован как массив из 4-байтовых целых чисел, и один бит каждого будет использоваться для хранения ваших данных. Теоретически интеллектуальный компилятор мог бы оптимизировать это, но я не стал бы рассчитывать на это.

Есть ли причина, по которой вы не хотите использовать std::bitset?

2

BitSet имеет more operations

+1

Это занимает меньше места. –

+1

Я не думаю, что его неправильный ответ. +1 для нейтрализации. – bjskishore123

0

Процитировать cplusplus.com's page on bitset: «Класс очень похож на обычный массив, но оптимизирует пространство для размещения». Если ваш ints равен 4 байтам, биты используют в 32 раза меньше места.

Даже делая bool bits[100], как предположил sbi, все еще хуже, чем битсет, потому что в большинстве реализаций есть> = 1-байтовое bools.

Если по причинам интеллектуального любопытства только, что вы хотели реализовать свой собственный BitSet, вы могли бы сделать это с помощью битовых масок:

typedef struct { 
    unsigned char bytes[100]; 
} MyBitset; 

bool getBit(MyBitset *bitset, int index) 
{ 
    int whichByte = index/8; 
    return bitset->bytes[whichByte] && (1 << (index = % 8)); 
} 

bool setBit(MyBitset *bitset, int index, bool newVal) 
{ 
    int whichByte = index/8; 

    if (newVal) 
    { 
    bitset->bytes[whichByte] |= (1 << (index = % 8)); 
    } 
    else 
    { 
    bitset->bytes[whichByte] &= ~(1 << (index = % 8)); 
    } 
} 

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

+3

В C++ единственная разница между классом и структурой заключается в том, что члены класса являются закрытыми по умолчанию, а члены структуры по умолчанию являются общедоступными. – M2tM

5

Хороший выбор зависит от того, как вы собираетесь использовать бит.

std::bitset<N> имеет фиксированный размер. Visual C++ 10.0 не соответствует требованиям. конструкторам; в общем, вы должны предоставить обходной путь. Это было, как это ни парадоксально, из-за того, что Microsoft считала ошибкой - они ввели конструктор, принимающий аргумент int, насколько я помню.

std::vector<bool> оптимизирован практически так же, как std::bitset. Стоимость: индексирование напрямую не предоставляет ссылку (нет ссылок на отдельные биты в C++), но вместо этого возвращает прокси-объект - это не то, что вы замечаете, пока не попытаетесь использовать его в качестве ссылки. Преимущество: минимальное хранение, и вектор может быть изменен по мере необходимости.

Просто используя, например, unsigned также является вариантом, если вы собираетесь иметь дело с небольшим количеством бит (на практике 32 или менее, хотя формальная гарантия составляет всего 16 бит).

Идентификаторы ALL UPPERCASE по умолчанию (кроме Microsoft) зарезервированы для макросов, чтобы уменьшить вероятность столкновений имен. Поэтому неплохо не использовать идентификаторы ALL UPPERCASE для чего-либо еще, кроме макросов. И всегда использовать ВСЕ идентификаторы UPPERCASE для макросов (это также облегчает их распознавание).

Приветствия & НТН.,

Смежные вопросы