2010-10-22 20 views
13

Quiero almacenar bits en una matriz (como la estructura). Así que se puede seguir cualquiera de los dos enfoques siguientesBit campo vs Bitset

número Enfoque 1 (AN 1)

struct BIT 
{ 
    int data : 1 
}; 

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

número Enfoque 2 (AN 2)

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

¿Por qué alguien prefiere un 2 a través de una 1?

+3

Para citar la página de cplusplus.com en bitset, "La clase es muy similar a una matriz regular, pero la optimización de la asignación de espacio". Si sus entradas son de 4 bytes, un conjunto de bits utiliza 32 veces menos espacio. – AlcubierreDrive

+2

Su estructura 'BIT' se alineará de todos modos a (al menos) un byte. – Archie

+0

@Jon, publica eso como respuesta. (Es un buen punto.) –

Respuesta

15

Debido enfoque nr. 2 realmente usa 100 bits de almacenamiento, más algunos gastos indirectos muy pequeños (constantes), mientras que nr. 1 generalmente usa cuatro bytes de almacenamiento por estructura Bit. En general, un struct tiene al menos un byte de gran tamaño según el estándar de 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"; 
} 

impresiones

400 
16 

Aparte de esto bitset, envuelve su matriz de bits en una representación de objeto bonito, con muchas operaciones útiles.

+0

¿Cómo es que la salida de 'sizeof (b)' es 16? 100 bits significa 100/8 bytes. ¿Qué me estoy perdiendo? – CLOWN

+1

Tiene que ser "redondeado" a un múltiplo de ocho, ya que un byte es la unidad de almacenamiento más pequeña que es directamente direccionable. Intenta compilar con 128 bits en el conjunto, entonces sigue siendo 16. 'bitset' usa algunos trucos para pretender que en realidad está abordando bits. –

+0

Mi comentario anterior estaba a la mitad. Se redondea a un múltiplo de 4 bytes, porque una unidad de cuatro bytes es la más rápida de procesar para una computadora de 32 bits. Pero en cualquier caso, un byte es la unidad direccionable más pequeña, por lo que es al menos 13 (100/8 = 12.5, y medio byte no es direccionable). Lo siento, viernes por la tarde. –

0

El enfoque número 1 probablemente se compilará como una matriz de enteros de 4 bytes, y se usará un bit de cada uno para almacenar sus datos. Teóricamente, un compilador inteligente podría optimizar esto, pero no contaría con ello.

¿Hay algún motivo por el que no desee utilizar std::bitset?

0

Para citar cplusplus.com's page on bitset, "La clase es muy similar a una matriz normal, pero optimiza la asignación de espacio". Si sus entradas son de 4 bytes, un conjunto de bits utiliza 32 veces menos espacio.

Incluso haciendo bool bits[100], como sbi sugirió, es aún peor que bitset, porque la mayoría de las implementaciones tienen bob> = 1 byte.

Si, por razones de curiosidad intelectual única, que quería poner en práctica su propia bitset, podría hacerlo a través de máscaras de bits:

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

(Lo siento por el uso de una estructura en lugar de una clase por cierto. Estoy pensando en C directamente porque estoy en medio de una tarea de bajo nivel para la escuela. Obviamente, dos grandes ventajas de utilizar una clase son la sobrecarga del operador y la capacidad de tener una matriz de tamaño variable)

+3

En C++ la única diferencia entre una clase y una estructura es que los miembros de la clase son privados por defecto y los miembros de la estructura son públicos por defecto. – M2tM

5

Una buena elección depende de cómo va a usar los bits.

std::bitset<N> es de tamaño fijo. Visual C++ 10.0 es wrt no conforme. a los constructores; en general, debe proporcionar una solución alternativa. Esto fue, irónicamente, debido a lo que Microsoft pensó que era una corrección de errores: introdujeron un constructor tomando el argumento int, según recuerdo.

std::vector<bool> está optimizado de la misma manera que std::bitset. Costo: la indexación no proporciona directamente una referencia (no hay referencias a bits individuales en C++), sino que devuelve un objeto proxy, que no es algo que notes hasta que intentes usarlo como referencia. Ventaja: almacenamiento mínimo, y el vector puede cambiar de tamaño según sea necesario.

Simplemente usando, por ejemplo, unsigned es también una opción, si va a tratar con un pequeño número de bits (en la práctica, 32 o menos, aunque la garantía formal es de solo 16 bits).

Finalmente, TODOS los identificadores MAYÚSCULAS son por convención (excepto Microsoft) reservados para macros, a fin de reducir la probabilidad de colisiones de nombres. Por lo tanto, es una buena idea no utilizar TODOS los identificadores MAYÚSCULAS para nada más que macros. Y para usar siempre TODOS los identificadores MAYÚSCULAS para macros (esto también hace que sea más fácil reconocerlos).

Saludos & HTH.,