2. Campos de Bit

Existe otro tipo de estructuras que consiste en empaquetar los campos de la estructura en el interior de enteros, usando bloques o conjuntos de bits paracada campo.

Por ejemplo, una variable char contiene ocho bits, de modo que dentro de ella podremos almacenar ocho campos de un bit, o cuatro de dos bits, o dosde tres y uno de dos, etc.

En una variable int de 16 bits podremos almacenar16 bits, etc.Debemos usar siempre valores de enteros sin signo, ya que el signo sealmacena en un bit del entero, el de mayor peso, y puede falsear los datos almacenados en la estructura.

Sintaxis:

struct [<nombre de la estructura>] {   unsigned <tipo_entero> <identifcador>:<núm_de_bits>;   } [<lista_variables>];

Hay algunas limitaciones, por ejemplo, un campo de bits no puede ocupar dos variables (miembros) distintos, todos sus bits tienen que estar en el mismo valor entero

Por ejemplo:


struct mapaBits {
unsigned char bit0:1;
unsigned char bit1:1;
unsigned char bit2:1;
unsigned char bit3:1;
unsigned char bit4:1;
unsigned char bit5:1;
unsigned char bit6:1;
unsigned char bit7:1;
};
struct mapaBits2 {
unsigned short int campo1:3;
unsigned short int campo2:4;
unsigned short int campo3:2;
unsigned short int campo4:1;
unsigned short int campo5:6;
};
struct mapaBits3 {
unsigned char campo1:5;
unsigned char campo2:5;
};

En el primer caso se divide un valor char sin signo en ocho campos de un bit cada uno:

En el segundo caso dividimos un valor entero sin signo de dieciséis bits en cinco campos de distintas longitudes:

Los valores del campo5 estarán limitados entre 0 y 63, que son los números que se pueden codificar con seis bits. Del mismo modo, el campo4 sólo puede valer 0 ó 1, etc.

En este ejemplo vemos que como no es posible empaquetar el campo2 dentro del mismo char que el campo1, se añade un segundo valor char, y se dejan sin usar los bits sobrantes.
También es posible combinar campos de bits con campos normales.


struct mapaBits2 {
int numero;
unsigned short int campo1:3;
unsigned short int campo2:4;
unsigned short int campo3:2;
unsigned short int campo4:1;
unsigned short int campo5:6;
float n;
};
Los campos de bits se tratan en general igual que cualquier otro de los campos de una estructura. Se les puede asignar valores (dentro del rango que admitan), pueden usarse en condicionales, imprimirse, etc.

#include <iostream>
using namespace std;
struct mapaBits2 {
unsigned short int campo1:3;
unsigned short int campo2:4;
unsigned short int campo3:2;
unsigned short int campo4:1;
unsigned short int campo5:6;
};
int main()
{
mapaBits2 x;
x.campo2 = 12;
x.campo4 = 1;
cout << x.campo2 << endl;
cout << x.campo4 << endl;
cin.get();
return 0;
}


No es normal usar estas estructuras en programas, salvo cuando se relacionan con ciertos dispositivos físicos, por ejemplo, para configurar un puerto serie en MS-DOS se usa una estructura empaquetada en un unsigned char, que indica los bits de datos, de parada, la paridad, etc, es decir, todos los parámetros del puerto. En general, para programas que no requieran estas estructuras, es mejor usar estructuras normales, ya que son mucho más rápidas.

Otro motivo que puede decidirnos por estas estructuras es el ahorro de espacio, ya sea en disco o en memoria. Si conocemos los límites de los campos que queremos almacenar, y podemos empaquetarlos en estructuras de mapas de bits podemos ahorrar mucho espacio.